[BACK]Return to job.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/job.c between version 1.125 and 1.126

version 1.125, 2012/09/21 08:18:40 version 1.126, 2012/10/02 10:29:30
Line 73 
Line 73 
  *      Job_Begin               execute commands attached to the .BEGIN target   *      Job_Begin               execute commands attached to the .BEGIN target
  *                              if any.   *                              if any.
  *   *
  *      Job_End                 Should cleanup any memory used.  
  *  
  *      can_start_job           Return true if we can start job   *      can_start_job           Return true if we can start job
  *   *
  *      Job_Empty               Return true if the job table is completely   *      Job_Empty               Return true if the job table is completely
Line 133 
Line 131 
 static Job *heldJobs;           /* Jobs not running yet because of expensive */  static Job *heldJobs;           /* Jobs not running yet because of expensive */
 static pid_t mypid;  static pid_t mypid;
   
 static volatile sig_atomic_t got_fatal;  static volatile sig_atomic_t got_fatal, got_other;
   
 static volatile sig_atomic_t got_SIGINT, got_SIGHUP, got_SIGQUIT, got_SIGTERM,  static volatile sig_atomic_t got_SIGINT, got_SIGHUP, got_SIGQUIT, got_SIGTERM,
     got_SIGINFO;      got_SIGINFO, got_SIGTSTP, got_SIGTTOU, got_SIGTTIN, got_SIGCONT,
       got_SIGWINCH;
   
 static sigset_t sigset, emptyset;  static sigset_t sigset, emptyset;
   
 static void handle_signal(int);  static void handle_fatal_signal(int);
   static void pass_job_control_signal(int);
 static void handle_siginfo(void);  static void handle_siginfo(void);
 static void postprocess_job(Job *, bool);  static void postprocess_job(Job *, bool);
 static Job *prepare_job(GNode *);  static Job *prepare_job(GNode *);
Line 157 
Line 157 
 static void setup_signal(int);  static void setup_signal(int);
 static void notice_signal(int);  static void notice_signal(int);
 static void setup_all_signals(void);  static void setup_all_signals(void);
 static void really_kill(int, pid_t);  static void setup_job_control_interrupts(void);
   
   static void
   print_error(Job *j, Job *k)
   {
           const char *type;
   
           if (j->exit_type == JOB_EXIT_BAD)
                   type = "Exit status";
           else if (j->exit_type == JOB_SIGNALED)
                   type = "Received signal";
           else
                   type = "Should not happen";
           fprintf(stderr, " %s %d (", type, j->code);
           fprintf(stderr, "line %lu",
               j->location->lineno);
           if (j == k)
                   fprintf(stderr, " of %s,", j->location->fname);
           else
                   fputs(",", stderr);
           if ((j->flags & (JOB_SILENT | JOB_IS_EXPENSIVE)) == JOB_SILENT)
                   fprintf(stderr, "\n     target %s: %s", j->node->name, j->cmd);
           else
                   fprintf(stderr, " target %s", j->node->name);
           fputs(")\n", stderr);
           free(j->cmd);
   }
   
 void  void
 print_errors(void)  print_errors(void)
 {  {
         Job *j;          Job *j, *k, *jnext;
         const char *previous = NULL;  
   
         fprintf(stderr, "\nStop in %s%c\n", Var_Value(".CURDIR"),          fprintf(stderr, "\nStop in %s%c\n", Var_Value(".CURDIR"),
             errorJobs ? ':' : '.');              errorJobs ? ':' : '.');
   
         for (j = errorJobs; j != NULL; j = j->next) {          while (errorJobs != NULL) {
                 const char *type;                  k = errorJobs;
                   errorJobs = NULL;
                 if (j->exit_type == JOB_EXIT_BAD)                  for (j = k; j != NULL; j = jnext) {
                         type = "Exit status";                          jnext = j->next;
                 else if (j->exit_type == JOB_SIGNALED)                          if (j->location->fname == k->location->fname)
                         type = "Received signal";                                  print_error(j, k);
                 else                          else {
                         type = "Should not happen";                                  j->next = errorJobs;
                 fprintf(stderr, " %s %d (", type, j->code);                                  errorJobs = j;
                 fprintf(stderr, "line %lu",                          }
                     j->location->lineno);                  }
                 if (j->location->fname == previous)  
                         fputs(",", stderr);  
                 else  
                         fprintf(stderr, " of %s,", j->location->fname);  
                 previous = j->location->fname;  
                 if ((j->flags & (JOB_SILENT | JOB_IS_EXPENSIVE)) == JOB_SILENT)  
                         fprintf(stderr, "\n     target %s: %s", j->node->name, j->cmd);  
                 else  
                         fprintf(stderr, " target %s", j->node->name);  
                 fputs(")\n", stderr);  
                 free(j->cmd);  
         }          }
 }  }
   
Line 206 
Line 220 
 static void  static void
 notice_signal(int sig)  notice_signal(int sig)
 {  {
   
         switch(sig) {          switch(sig) {
         case SIGINT:          case SIGINT:
                 got_SIGINT++;                  got_SIGINT++;
Line 228 
Line 243 
                 break;                  break;
         case SIGCHLD:          case SIGCHLD:
                 break;                  break;
           case SIGTSTP:
                   got_SIGTSTP++;
                   got_other = 1;
                   break;
           case SIGTTOU:
                   got_SIGTTOU++;
                   got_other = 1;
                   break;
           case SIGTTIN:
                   got_SIGTTIN++;
                   got_other = 1;
                   break;
           case SIGCONT:
                   got_SIGCONT++;
                   got_other = 1;
                   break;
           case SIGWINCH:
                   got_SIGWINCH++;
                   got_other = 1;
                   break;
         }          }
 }  }
   
   static void
   setup_job_control_interrupts(void)
   {
           setup_signal(SIGTSTP);
           setup_signal(SIGTTOU);
           setup_signal(SIGTTIN);
   }
   
 void  void
 setup_all_signals(void)  setup_all_signals(void)
 {  {
Line 249 
Line 292 
         /* Have to see SIGCHLD */          /* Have to see SIGCHLD */
         setup_signal(SIGCHLD);          setup_signal(SIGCHLD);
         got_fatal = 0;          got_fatal = 0;
           setup_job_control_interrupts();
           setup_signal(SIGWINCH);
           setup_signal(SIGCONT);
           got_other = 0;
 }  }
   
 static void  static void
 handle_siginfo(void)  handle_siginfo(void)
 {  {
           static BUFFER buf;
           static size_t length = 0;
   
         Job *job;          Job *job;
         BUFFER buf;  
         bool first = true;          bool first = true;
   
         got_SIGINFO = 0;          got_SIGINFO = 0;
         /* we have to store the info in a buffer, because status from all          /* we have to store the info in a buffer, because status from all
          * makes running would get intermixed otherwise           * makes running would get intermixed otherwise
          */           */
         Buf_Init(&buf, 0);  
   
         Buf_printf(&buf, "%s in %s: ", Var_Value("MAKE"), Var_Value(".CURDIR"));          if (length == 0) {
                   Buf_Init(&buf, 0);
                   Buf_printf(&buf, "%s in %s: ", Var_Value("MAKE"), Var_Value(".CURDIR"));
                   length = Buf_Size(&buf);
           } else
                   Buf_Truncate(&buf, length);
   
         for (job = runningJobs; job != NULL ; job = job->next) {          for (job = runningJobs; job != NULL ; job = job->next) {
                 if (!first)                  if (!first)
Line 275 
Line 328 
         Buf_puts(&buf, first ? "nothing running\n" : "\n");          Buf_puts(&buf, first ? "nothing running\n" : "\n");
   
         fputs(Buf_Retrieve(&buf), stderr);          fputs(Buf_Retrieve(&buf), stderr);
         Buf_Destroy(&buf);  
 }  }
   
 void  void
Line 283 
Line 335 
 {  {
         if (got_SIGINFO)          if (got_SIGINFO)
                 handle_siginfo();                  handle_siginfo();
           while (got_other) {
                   got_other = 0;
                   if (got_SIGWINCH) {
                           got_SIGWINCH=0;
                           pass_job_control_signal(SIGWINCH);
                   }
                   if (got_SIGTTIN) {
                           got_SIGTTIN=0;
                           pass_job_control_signal(SIGTTIN);
                   }
                   if (got_SIGTTOU) {
                           got_SIGTTOU=0;
                           pass_job_control_signal(SIGTTOU);
                   }
                   if (got_SIGTSTP) {
                           got_SIGTSTP=0;
                           pass_job_control_signal(SIGTSTP);
                   }
                   if (got_SIGCONT) {
                           got_SIGCONT=0;
                           pass_job_control_signal(SIGCONT);
                   }
           }
         while (got_fatal) {          while (got_fatal) {
                 got_fatal = 0;                  got_fatal = 0;
                 aborting = ABORT_INTERRUPT;                  aborting = ABORT_INTERRUPT;
   
                 if (got_SIGINT) {                  if (got_SIGINT) {
                         got_SIGINT=0;                          got_SIGINT=0;
                         handle_signal(SIGINT);                          handle_fatal_signal(SIGINT);
                 }                  }
                 if (got_SIGHUP) {                  if (got_SIGHUP) {
                         got_SIGHUP=0;                          got_SIGHUP=0;
                         handle_signal(SIGHUP);                          handle_fatal_signal(SIGHUP);
                 }                  }
                 if (got_SIGQUIT) {                  if (got_SIGQUIT) {
                         got_SIGQUIT=0;                          got_SIGQUIT=0;
                         handle_signal(SIGQUIT);                          handle_fatal_signal(SIGQUIT);
                 }                  }
                 if (got_SIGTERM) {                  if (got_SIGTERM) {
                         got_SIGTERM=0;                          got_SIGTERM=0;
                         handle_signal(SIGTERM);                          handle_fatal_signal(SIGTERM);
                 }                  }
         }          }
 }  }
Line 353 
Line 428 
                 aborting = ABORT_ERROR;                  aborting = ABORT_ERROR;
   
         if (aborting == ABORT_ERROR && DEBUG(QUICKDEATH))          if (aborting == ABORT_ERROR && DEBUG(QUICKDEATH))
                 handle_signal(SIGINT);                  handle_fatal_signal(SIGINT);
         if (aborting == ABORT_ERROR && Job_Empty())          if (aborting == ABORT_ERROR && Job_Empty())
                 Finish();                  Finish();
 }  }
Line 517 
Line 592 
 Job_Make(GNode *gn)  Job_Make(GNode *gn)
 {  {
         Job *job;          Job *job;
         bool finished;  
   
         job = prepare_job(gn);          job = prepare_job(gn);
         if (!job)          if (!job)
Line 700 
Line 774 
 }  }
   
 static void  static void
 really_kill(pid_t pid, int sig)  pass_job_control_signal(int signo)
 {  {
         killpg(pid, sig);          Job *job;
         if (killpg(pid, sig) == - 1 && errno == ESRCH)  
                 kill(pid, sig);          debug_job_printf("pass_job_control_signal(%d) called.\n", signo);
   
   
           for (job = runningJobs; job != NULL; job = job->next) {
                   debug_job_printf("pass_job_control_signal to "
                       "child %ld running %s.\n", (long)job->pid,
                       job->node->name);
                   killpg(job->pid, signo);
           }
           /* after forwarding the signal, those should interrupt us */
           if (signo == SIGTSTP || signo == SIGTTOU || signo == SIGTTIN) {
                   sigprocmask(SIG_BLOCK, &sigset, NULL);
                   signal(signo, SIG_DFL);
                   kill(getpid(), signo);
                   sigprocmask(SIG_SETMASK, &emptyset, NULL);
           }
           /* SIGWINCH is irrelevant for us, SIGCONT must put back normal
            * handling for other job control signals */
           if (signo == SIGCONT)
                   setup_job_control_interrupts();
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * handle_signal --   * handle_fatal_signal --
  *      Handle the receipt of an interrupt.   *      Handle the receipt of a fatal interrupt
  *   *
  * Side Effects:   * Side Effects:
  *      All children are killed. Another job may be started if the   *      All children are killed. Another job may be started if there
  *      .INTERRUPT target was given.   *      is an interrupt target and the signal was SIGINT.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 handle_signal(int signo)  handle_fatal_signal(int signo)
 {  {
         Job *job;          Job *job;
   
         debug_job_printf("handle_signal(%d) called.\n", signo);          debug_job_printf("handle_fatal_signal(%d) called.\n", signo);
   
   
         for (job = runningJobs; job != NULL; job = job->next) {          for (job = runningJobs; job != NULL; job = job->next) {
Line 731 
Line 825 
                         if (!noExecute && eunlink(file) != -1)                          if (!noExecute && eunlink(file) != -1)
                                 Error("*** %s removed", file);                                  Error("*** %s removed", file);
                 }                  }
                 debug_job_printf("handle_signal passing signal to "                  debug_job_printf("handle_fatal_signal: passing to "
                     "child %ld running %s.\n", (long)job->pid,                      "child %ld running %s.\n", (long)job->pid,
                     job->node->name);                      job->node->name);
                 really_kill(job->pid, signo);                  killpg(job->pid, signo);
         }          }
   
         if (signo == SIGINT && !touchFlag) {          if (signo == SIGINT && !touchFlag) {
Line 750 
Line 844 
         /* die by that signal */          /* die by that signal */
         sigprocmask(SIG_BLOCK, &sigset, NULL);          sigprocmask(SIG_BLOCK, &sigset, NULL);
         signal(signo, SIG_DFL);          signal(signo, SIG_DFL);
         really_kill(getpid(), signo);          kill(getpid(), signo);
         sigprocmask(SIG_SETMASK, &emptyset, NULL);          sigprocmask(SIG_SETMASK, &emptyset, NULL);
         /*NOTREACHED*/          /*NOTREACHED*/
 }  }
Line 789 
Line 883 
         }          }
 }  }
   
 #ifdef CLEANUP  
 void  
 Job_End(void)  
 {  
 }  
 #endif  
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Job_Wait --   * Job_Wait --
Line 835 
Line 922 
         aborting = ABORT_ERROR;          aborting = ABORT_ERROR;
   
         for (job = runningJobs; job != NULL; job = job->next) {          for (job = runningJobs; job != NULL; job = job->next) {
                 really_kill(job->pid, SIGINT);                  killpg(job->pid, SIGINT);
                 really_kill(job->pid, SIGKILL);                  killpg(job->pid, SIGKILL);
         }          }
   
         /*          /*

Legend:
Removed from v.1.125  
changed lines
  Added in v.1.126