1 /* $OpenBSD: job.c,v 1.160 2020/01/29 17:06:51 espie Exp $ */ 2 /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */ 3 4 /* 5 * Copyright (c) 2012 Marc Espie. 6 * 7 * Extensive code modifications for the OpenBSD project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 32 * Copyright (c) 1988, 1989 by Adam de Boor 33 * Copyright (c) 1989 by Berkeley Softworks 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Adam de Boor. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /*- 65 * job.c -- 66 * handle the creation etc. of our child processes. 67 * 68 * Interface: 69 * Job_Make Start the creation of the given target. 70 * 71 * Job_Init Called to initialize this module. 72 * 73 * can_start_job Return true if we can start job 74 * 75 * Job_Empty Return true if the job table is completely 76 * empty. 77 * 78 * Job_AbortAll Abort all current jobs. It doesn't 79 * handle output or do anything for the jobs, 80 * just kills them. 81 * 82 * Job_Wait Wait for all running jobs to finish. 83 */ 84 85 #include <sys/types.h> 86 #include <sys/wait.h> 87 #include <ctype.h> 88 #include <errno.h> 89 #include <fcntl.h> 90 #include <signal.h> 91 #include <stdarg.h> 92 #include <stdio.h> 93 #include <stdlib.h> 94 #include <string.h> 95 #include <unistd.h> 96 #include "config.h" 97 #include "defines.h" 98 #include "job.h" 99 #include "engine.h" 100 #include "pathnames.h" 101 #include "var.h" 102 #include "targ.h" 103 #include "error.h" 104 #include "extern.h" 105 #include "lst.h" 106 #include "gnode.h" 107 #include "memory.h" 108 #include "buf.h" 109 #include "enginechoice.h" 110 111 static int aborting = 0; /* why is the make aborting? */ 112 #define ABORT_ERROR 1 /* Because of an error */ 113 #define ABORT_INTERRUPT 2 /* Because it was interrupted */ 114 #define ABORT_WAIT 3 /* Waiting for jobs to finish */ 115 116 static bool no_new_jobs; /* Mark recursive shit so we shouldn't start 117 * something else at the same time 118 */ 119 bool sequential; 120 Job *runningJobs; /* Jobs currently running a process */ 121 Job *errorJobs; /* Jobs in error at end */ 122 Job *availableJobs; /* Pool of available jobs */ 123 static Job *heldJobs; /* Jobs not running yet because of expensive */ 124 static pid_t mypid; /* Used for printing debugging messages */ 125 static Job *extra_job; /* Needed for .INTERRUPT */ 126 127 static volatile sig_atomic_t got_fatal; 128 129 static volatile sig_atomic_t got_SIGINT, got_SIGHUP, got_SIGQUIT, got_SIGTERM, 130 got_SIGINFO; 131 132 static sigset_t sigset, emptyset, origset; 133 134 static void handle_fatal_signal(int); 135 static void handle_siginfo(void); 136 static void postprocess_job(Job *); 137 static void determine_job_next_step(Job *); 138 static void may_continue_job(Job *); 139 static Job *reap_finished_job(pid_t); 140 static bool reap_jobs(void); 141 static void may_continue_heldback_jobs(void); 142 143 static bool expensive_job(Job *); 144 static bool expensive_command(const char *); 145 static void setup_signal(int); 146 static void notice_signal(int); 147 static void setup_all_signals(void); 148 static const char *really_kill(Job *, int); 149 static void debug_kill_printf(const char *, ...); 150 static void debug_vprintf(const char *, va_list); 151 static void may_remove_target(Job *); 152 static void print_error(Job *); 153 static void internal_print_errors(void); 154 155 static int dying_signal = 0; 156 157 const char * basedirectory = NULL; 158 159 static const char * 160 really_kill(Job *job, int signo) 161 { 162 pid_t pid = job->pid; 163 if (getpgid(pid) != getpgrp()) { 164 if (killpg(pid, signo) == 0) 165 return "group got signal"; 166 pid = -pid; 167 } else { 168 if (kill(pid, signo) == 0) 169 return "process got signal"; 170 } 171 if (errno == ESRCH) 172 job->flags |= JOB_LOST; 173 return strerror(errno); 174 } 175 176 static void 177 may_remove_target(Job *j) 178 { 179 int dying = check_dying_signal(); 180 181 if (dying && !noExecute && !Targ_Precious(j->node)) { 182 const char *file = Var(TARGET_INDEX, j->node); 183 int r = eunlink(file); 184 185 if (DEBUG(JOB) && r == -1) 186 fprintf(stderr, " *** would unlink %s\n", file); 187 if (r != -1) 188 fprintf(stderr, " *** %s removed\n", file); 189 } 190 } 191 192 static void 193 buf_addcurdir(BUFFER *buf) 194 { 195 const char *v = Var_Value(".CURDIR"); 196 if (basedirectory != NULL) { 197 size_t len = strlen(basedirectory); 198 if (strncmp(basedirectory, v, len) == 0 && 199 v[len] == '/') { 200 v += len+1; 201 } else if (strcmp(basedirectory, v) == 0) { 202 Buf_AddString(buf, "."); 203 return; 204 } 205 } 206 Buf_AddString(buf, v); 207 } 208 209 static const char * 210 shortened_curdir(void) 211 { 212 static BUFFER buf; 213 static bool first = true; 214 if (first) { 215 Buf_Init(&buf, 0); 216 buf_addcurdir(&buf); 217 first = false; 218 } 219 return Buf_Retrieve(&buf); 220 } 221 222 static void 223 quick_error(Job *j, int signo, bool first) 224 { 225 if (first) { 226 fprintf(stderr, "*** Signal SIG%s", sys_signame[signo]); 227 fprintf(stderr, " in %s (", shortened_curdir()); 228 } else 229 fprintf(stderr, " "); 230 231 fprintf(stderr, "%s", j->node->name); 232 free(j->cmd); 233 } 234 235 static void 236 print_error(Job *j) 237 { 238 static bool first = true; 239 BUFFER buf; 240 241 Buf_Init(&buf, 0); 242 243 if (j->exit_type == JOB_EXIT_BAD) 244 Buf_printf(&buf, "*** Error %d", j->code); 245 else if (j->exit_type == JOB_SIGNALED) { 246 if (j->code < NSIG) 247 Buf_printf(&buf, "*** Signal SIG%s", 248 sys_signame[j->code]); 249 else 250 Buf_printf(&buf, "*** unknown signal %d", j->code); 251 } else 252 Buf_printf(&buf, "*** Should not happen %d/%d", 253 j->exit_type, j->code); 254 if (DEBUG(KILL) && (j->flags & JOB_LOST)) 255 Buf_AddChar(&buf, '!'); 256 if (first) { 257 Buf_AddString(&buf, " in "); 258 buf_addcurdir(&buf); 259 first = false; 260 } 261 Buf_printf(&buf, " (%s:%lu", j->location->fname, j->location->lineno); 262 Buf_printf(&buf, " '%s'", j->node->name); 263 if ((j->flags & (JOB_SILENT | JOB_IS_EXPENSIVE)) == JOB_SILENT 264 && Buf_Size(&buf) < 140-2) { 265 size_t len = strlen(j->cmd); 266 Buf_AddString(&buf, ": "); 267 if (len + Buf_Size(&buf) < 140) 268 Buf_AddString(&buf, j->cmd); 269 else { 270 Buf_AddChars(&buf, 140 - Buf_Size(&buf), j->cmd); 271 Buf_AddString(&buf, "..."); 272 } 273 } 274 fprintf(stderr, "%s)\n", Buf_Retrieve(&buf)); 275 Buf_Destroy(&buf); 276 free(j->cmd); 277 } 278 static void 279 quick_summary(int signo) 280 { 281 Job *j, *k, *jnext; 282 bool first = true; 283 284 k = errorJobs; 285 errorJobs = NULL; 286 for (j = k; j != NULL; j = jnext) { 287 jnext = j->next; 288 if ((j->exit_type == JOB_EXIT_BAD && j->code == signo+128) || 289 (j->exit_type == JOB_SIGNALED && j->code == signo)) { 290 quick_error(j, signo, first); 291 first = false; 292 } else { 293 j->next = errorJobs; 294 errorJobs = j; 295 } 296 } 297 if (!first) 298 fprintf(stderr, ")\n"); 299 } 300 301 static void 302 internal_print_errors() 303 { 304 Job *j, *k, *jnext; 305 int dying; 306 307 if (!errorJobs) 308 fprintf(stderr, "Stop in %s\n", shortened_curdir()); 309 310 for (j = errorJobs; j != NULL; j = j->next) 311 may_remove_target(j); 312 dying = check_dying_signal(); 313 if (dying) 314 quick_summary(dying); 315 /* Print errors grouped by file name. */ 316 while (errorJobs != NULL) { 317 /* Select the first job. */ 318 k = errorJobs; 319 errorJobs = NULL; 320 for (j = k; j != NULL; j = jnext) { 321 jnext = j->next; 322 if (j->location->fname == k->location->fname) 323 /* Print errors with the same filename. */ 324 print_error(j); 325 else { 326 /* Keep others for the next iteration. */ 327 j->next = errorJobs; 328 errorJobs = j; 329 } 330 } 331 } 332 } 333 334 void 335 print_errors(void) 336 { 337 handle_all_signals(); 338 internal_print_errors(); 339 } 340 341 static void 342 setup_signal(int sig) 343 { 344 if (signal(sig, SIG_IGN) != SIG_IGN) { 345 (void)signal(sig, notice_signal); 346 sigaddset(&sigset, sig); 347 } 348 } 349 350 static void 351 notice_signal(int sig) 352 { 353 354 switch(sig) { 355 case SIGINT: 356 got_SIGINT++; 357 got_fatal = 1; 358 break; 359 case SIGHUP: 360 got_SIGHUP++; 361 got_fatal = 1; 362 break; 363 case SIGQUIT: 364 got_SIGQUIT++; 365 got_fatal = 1; 366 break; 367 case SIGTERM: 368 got_SIGTERM++; 369 got_fatal = 1; 370 break; 371 case SIGINFO: 372 got_SIGINFO++; 373 break; 374 case SIGCHLD: 375 break; 376 } 377 } 378 379 void 380 Sigset_Init() 381 { 382 sigemptyset(&emptyset); 383 sigprocmask(SIG_BLOCK, &emptyset, &origset); 384 } 385 386 static void 387 setup_all_signals(void) 388 { 389 sigemptyset(&sigset); 390 /* 391 * Catch the four signals that POSIX specifies if they aren't ignored. 392 * handle_signal will take care of calling JobInterrupt if appropriate. 393 */ 394 setup_signal(SIGINT); 395 setup_signal(SIGHUP); 396 setup_signal(SIGQUIT); 397 setup_signal(SIGTERM); 398 /* Display running jobs on SIGINFO */ 399 setup_signal(SIGINFO); 400 /* Have to see SIGCHLD */ 401 setup_signal(SIGCHLD); 402 got_fatal = 0; 403 } 404 405 static void 406 handle_siginfo(void) 407 { 408 static BUFFER buf; 409 static size_t length = 0; 410 411 Job *job; 412 bool first = true; 413 414 got_SIGINFO = 0; 415 /* we have to store the info in a buffer, because status from all 416 * makes running would get intermixed otherwise 417 */ 418 419 if (length == 0) { 420 Buf_Init(&buf, 0); 421 Buf_printf(&buf, "%s in ", Var_Value("MAKE")); 422 buf_addcurdir(&buf); 423 Buf_AddString(&buf, ": "); 424 length = Buf_Size(&buf); 425 } else 426 Buf_Truncate(&buf, length); 427 428 for (job = runningJobs; job != NULL ; job = job->next) { 429 if (!first) 430 Buf_puts(&buf, ", "); 431 first = false; 432 Buf_puts(&buf, job->node->name); 433 } 434 Buf_puts(&buf, first ? "nothing running\n" : "\n"); 435 436 fputs(Buf_Retrieve(&buf), stderr); 437 } 438 439 int 440 check_dying_signal(void) 441 { 442 sigset_t set; 443 if (dying_signal) 444 return dying_signal; 445 sigpending(&set); 446 if (got_SIGINT || sigismember(&set, SIGINT)) 447 return dying_signal = SIGINT; 448 if (got_SIGHUP || sigismember(&set, SIGHUP)) 449 return dying_signal = SIGHUP; 450 if (got_SIGQUIT || sigismember(&set, SIGQUIT)) 451 return dying_signal = SIGQUIT; 452 if (got_SIGTERM || sigismember(&set, SIGTERM)) 453 return dying_signal = SIGTERM; 454 return 0; 455 } 456 457 void 458 handle_all_signals(void) 459 { 460 if (got_SIGINFO) 461 handle_siginfo(); 462 while (got_fatal) { 463 got_fatal = 0; 464 aborting = ABORT_INTERRUPT; 465 466 if (got_SIGINT) { 467 got_SIGINT=0; 468 handle_fatal_signal(SIGINT); 469 } 470 if (got_SIGHUP) { 471 got_SIGHUP=0; 472 handle_fatal_signal(SIGHUP); 473 } 474 if (got_SIGQUIT) { 475 got_SIGQUIT=0; 476 handle_fatal_signal(SIGQUIT); 477 } 478 if (got_SIGTERM) { 479 got_SIGTERM=0; 480 handle_fatal_signal(SIGTERM); 481 } 482 } 483 } 484 485 static void 486 debug_vprintf(const char *fmt, va_list va) 487 { 488 (void)printf("[%ld] ", (long)mypid); 489 (void)vprintf(fmt, va); 490 fflush(stdout); 491 } 492 493 void 494 debug_job_printf(const char *fmt, ...) 495 { 496 if (DEBUG(JOB)) { 497 va_list va; 498 va_start(va, fmt); 499 debug_vprintf(fmt, va); 500 va_end(va); 501 } 502 } 503 504 static void 505 debug_kill_printf(const char *fmt, ...) 506 { 507 if (DEBUG(KILL)) { 508 va_list va; 509 va_start(va, fmt); 510 debug_vprintf(fmt, va); 511 va_end(va); 512 } 513 } 514 515 /*- 516 *----------------------------------------------------------------------- 517 * postprocess_job -- 518 * Do final processing for the given job including updating 519 * parents and starting new jobs as available/necessary. 520 * 521 * Side Effects: 522 * If we got an error and are aborting (aborting == ABORT_ERROR) and 523 * the job list is now empty, we are done for the day. 524 * If we recognized an error we set the aborting flag 525 * to ABORT_ERROR so no more jobs will be started. 526 *----------------------------------------------------------------------- 527 */ 528 /*ARGSUSED*/ 529 530 static void 531 postprocess_job(Job *job) 532 { 533 if (job->exit_type == JOB_EXIT_OKAY && 534 aborting != ABORT_ERROR && 535 aborting != ABORT_INTERRUPT) { 536 /* As long as we aren't aborting and the job didn't return a 537 * non-zero status that we shouldn't ignore, we call 538 * Make_Update to update the parents. */ 539 job->node->built_status = REBUILT; 540 engine_node_updated(job->node); 541 } 542 if (job->flags & JOB_KEEPERROR) { 543 job->next = errorJobs; 544 errorJobs = job; 545 } else { 546 job->next = availableJobs; 547 availableJobs = job; 548 } 549 550 if (errorJobs != NULL && aborting != ABORT_INTERRUPT) 551 aborting = ABORT_ERROR; 552 553 if (aborting == ABORT_ERROR && DEBUG(QUICKDEATH)) 554 handle_fatal_signal(SIGINT); 555 if (aborting == ABORT_ERROR && Job_Empty()) 556 Finish(); 557 } 558 559 /* expensive jobs handling: in order to avoid forking an exponential number 560 * of jobs, make tries to figure out "recursive make" configurations. 561 * It may err on the side of caution. 562 * Basically, a command is "expensive" if it's likely to fork an extra 563 * level of make: either by looking at the command proper, or if it has 564 * some specific qualities ('+cmd' are likely to be recursive, as are 565 * .MAKE: commands). It's possible to explicitly say some targets are 566 * expensive or cheap with .EXPENSIVE or .CHEAP. 567 * 568 * While an expensive command is running, no_new_jobs 569 * is set, so jobs that would fork new processes are accumulated in the 570 * heldJobs list instead. 571 * 572 * XXX This heuristics is also used on error exit: we display silent commands 573 * that failed, unless those ARE expensive commands: expensive commands are 574 * likely to not be failing by themselves, but to be the result of a cascade of 575 * failures in descendant makes. 576 */ 577 void 578 determine_expensive_job(Job *job) 579 { 580 if (expensive_job(job)) { 581 job->flags |= JOB_IS_EXPENSIVE; 582 no_new_jobs = true; 583 } else 584 job->flags &= ~JOB_IS_EXPENSIVE; 585 if (DEBUG(EXPENSIVE)) 586 fprintf(stderr, "[%ld] Target %s running %.50s: %s\n", 587 (long)mypid, job->node->name, job->cmd, 588 job->flags & JOB_IS_EXPENSIVE ? "expensive" : "cheap"); 589 } 590 591 static bool 592 expensive_job(Job *job) 593 { 594 if (job->node->type & OP_CHEAP) 595 return false; 596 if (job->node->type & (OP_EXPENSIVE | OP_MAKE)) 597 return true; 598 return expensive_command(job->cmd); 599 } 600 601 static bool 602 expensive_command(const char *s) 603 { 604 const char *p; 605 bool include = false; 606 bool expensive = false; 607 608 /* okay, comments are cheap, always */ 609 if (*s == '#') 610 return false; 611 /* and commands we always execute are expensive */ 612 if (*s == '+') 613 return true; 614 615 for (p = s; *p != '\0'; p++) { 616 if (*p == ' ' || *p == '\t') { 617 include = false; 618 if (p[1] == '-' && p[2] == 'I') 619 include = true; 620 } 621 if (include) 622 continue; 623 /* KMP variant, avoid looking twice at the same 624 * letter. 625 */ 626 if (*p != 'm') 627 continue; 628 if (p[1] != 'a') 629 continue; 630 p++; 631 if (p[1] != 'k') 632 continue; 633 p++; 634 if (p[1] != 'e') 635 continue; 636 p++; 637 expensive = true; 638 while (p[1] != '\0' && p[1] != ' ' && p[1] != '\t') { 639 if (p[1] == '.' || p[1] == '/') { 640 expensive = false; 641 break; 642 } 643 p++; 644 } 645 if (expensive) 646 return true; 647 } 648 return false; 649 } 650 651 static void 652 may_continue_job(Job *job) 653 { 654 if (no_new_jobs) { 655 if (DEBUG(EXPENSIVE)) 656 fprintf(stderr, "[%ld] expensive -> hold %s\n", 657 (long)mypid, job->node->name); 658 job->next = heldJobs; 659 heldJobs = job; 660 } else { 661 bool finished = job_run_next(job); 662 if (finished) 663 postprocess_job(job); 664 else if (!sequential) 665 determine_expensive_job(job); 666 } 667 } 668 669 static void 670 may_continue_heldback_jobs() 671 { 672 while (!no_new_jobs) { 673 if (heldJobs != NULL) { 674 Job *job = heldJobs; 675 heldJobs = heldJobs->next; 676 if (DEBUG(EXPENSIVE)) 677 fprintf(stderr, "[%ld] cheap -> release %s\n", 678 (long)mypid, job->node->name); 679 may_continue_job(job); 680 } else 681 break; 682 } 683 } 684 685 /*- 686 *----------------------------------------------------------------------- 687 * Job_Make -- 688 * Start a target-creation process going for the target described 689 * by the graph node gn. 690 * 691 * Side Effects: 692 * A new Job node is created and its commands continued, which 693 * may fork the first command of that job. 694 *----------------------------------------------------------------------- 695 */ 696 void 697 Job_Make(GNode *gn) 698 { 699 Job *job = availableJobs; 700 701 assert(job != NULL); 702 availableJobs = availableJobs->next; 703 job_attach_node(job, gn); 704 may_continue_job(job); 705 } 706 707 static void 708 determine_job_next_step(Job *job) 709 { 710 if (job->flags & JOB_IS_EXPENSIVE) { 711 no_new_jobs = false; 712 if (DEBUG(EXPENSIVE)) 713 fprintf(stderr, "[%ld] " 714 "Returning from expensive target %s, " 715 "allowing new jobs\n", (long)mypid, 716 job->node->name); 717 } 718 719 if (job->exit_type != JOB_EXIT_OKAY || job->next_cmd == NULL) 720 postprocess_job(job); 721 else 722 may_continue_job(job); 723 } 724 725 /* 726 * job = reap_finished_job(pid): 727 * retrieve and remove a job from runningJobs, based on its pid 728 * 729 * Note that we remove it right away, so that handle_signals() 730 * is accurate. 731 */ 732 static Job * 733 reap_finished_job(pid_t pid) 734 { 735 Job **j, *job; 736 737 for (j = &runningJobs; *j != NULL; j = &((*j)->next)) 738 if ((*j)->pid == pid) { 739 job = *j; 740 *j = job->next; 741 return job; 742 } 743 744 return NULL; 745 } 746 747 /* 748 * classic waitpid handler: retrieve as many dead children as possible. 749 * returns true if succesful 750 */ 751 static bool 752 reap_jobs(void) 753 { 754 pid_t pid; /* pid of dead child */ 755 int status; /* Exit/termination status */ 756 bool reaped = false; 757 Job *job; 758 759 while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { 760 if (WIFSTOPPED(status)) 761 continue; 762 reaped = true; 763 job = reap_finished_job(pid); 764 765 if (job == NULL) { 766 Punt("Child (%ld) with status %d not in table?", 767 (long)pid, status); 768 } else { 769 handle_job_status(job, status); 770 determine_job_next_step(job); 771 } 772 may_continue_heldback_jobs(); 773 } 774 /* sanity check, should not happen */ 775 if (pid == -1 && errno == ECHILD && runningJobs != NULL) 776 Punt("Process has no children, but runningJobs is not empty ?"); 777 return reaped; 778 } 779 780 void 781 reset_signal_mask() 782 { 783 sigprocmask(SIG_SETMASK, &origset, NULL); 784 } 785 786 void 787 handle_running_jobs(void) 788 { 789 /* reaping children in the presence of caught signals */ 790 791 /* first, we make sure to hold on new signals, to synchronize 792 * reception of new stuff on sigsuspend 793 */ 794 sigprocmask(SIG_BLOCK, &sigset, NULL); 795 /* note this will NOT loop until runningJobs == NULL. 796 * It's merely an optimisation, namely that we don't need to go 797 * through the logic if no job is present. As soon as a job 798 * gets reaped, we WILL exit the loop through the break. 799 */ 800 while (runningJobs != NULL) { 801 /* did we already have pending stuff that advances things ? 802 * then handle_all_signals() will not return 803 * or reap_jobs() will reap_jobs() 804 */ 805 handle_all_signals(); 806 if (reap_jobs()) 807 break; 808 /* okay, so it's safe to suspend, we have nothing to do but 809 * wait... 810 */ 811 sigsuspend(&emptyset); 812 } 813 reset_signal_mask(); 814 } 815 816 void 817 loop_handle_running_jobs() 818 { 819 while (runningJobs != NULL) 820 handle_running_jobs(); 821 } 822 823 void 824 Job_Init(int maxJobs) 825 { 826 Job *j; 827 int i; 828 829 runningJobs = NULL; 830 heldJobs = NULL; 831 errorJobs = NULL; 832 availableJobs = NULL; 833 sequential = maxJobs == 1; 834 835 /* we allocate n+1 jobs, since we may need an extra job for 836 * running .INTERRUPT. */ 837 j = ereallocarray(NULL, sizeof(Job), maxJobs+1); 838 for (i = 0; i != maxJobs; i++) { 839 j[i].next = availableJobs; 840 availableJobs = &j[i]; 841 } 842 extra_job = &j[maxJobs]; 843 mypid = getpid(); 844 845 aborting = 0; 846 setup_all_signals(); 847 } 848 849 bool 850 can_start_job(void) 851 { 852 if (aborting || availableJobs == NULL) 853 return false; 854 else 855 return true; 856 } 857 858 bool 859 Job_Empty(void) 860 { 861 return runningJobs == NULL; 862 } 863 864 /*- 865 *----------------------------------------------------------------------- 866 * handle_fatal_signal -- 867 * Handle the receipt of a fatal interrupt 868 * 869 * Side Effects: 870 * All children are killed. Another job may be started if there 871 * is an interrupt target and the signal was SIGINT. 872 *----------------------------------------------------------------------- 873 */ 874 static void 875 handle_fatal_signal(int signo) 876 { 877 Job *job; 878 879 debug_kill_printf("handle_fatal_signal(%d) called.\n", signo); 880 881 dying_signal = signo; 882 for (job = runningJobs; job != NULL; job = job->next) { 883 debug_kill_printf("passing to " 884 "child %ld running %s: %s\n", (long)job->pid, 885 job->node->name, really_kill(job, signo)); 886 may_remove_target(job); 887 } 888 889 if (signo == SIGINT && !touchFlag) { 890 if ((interrupt_node->type & OP_DUMMY) == 0) { 891 ignoreErrors = false; 892 extra_job->next = availableJobs; 893 availableJobs = extra_job; 894 Job_Make(interrupt_node); 895 } 896 } 897 loop_handle_running_jobs(); 898 internal_print_errors(); 899 900 /* die by that signal */ 901 sigprocmask(SIG_BLOCK, &sigset, NULL); 902 signal(signo, SIG_DFL); 903 kill(getpid(), signo); 904 sigprocmask(SIG_SETMASK, &emptyset, NULL); 905 /*NOTREACHED*/ 906 fprintf(stderr, "This should never happen\n"); 907 exit(1); 908 } 909 910 /*- 911 *----------------------------------------------------------------------- 912 * Job_Wait -- 913 * Waits for all running jobs to finish and returns. Sets 'aborting' 914 * to ABORT_WAIT to prevent other jobs from starting. 915 * 916 * Side Effects: 917 * Currently running jobs finish. 918 * 919 *----------------------------------------------------------------------- 920 */ 921 void 922 Job_Wait(void) 923 { 924 aborting = ABORT_WAIT; 925 loop_handle_running_jobs(); 926 aborting = 0; 927 } 928 929 /*- 930 *----------------------------------------------------------------------- 931 * Job_AbortAll -- 932 * Abort all currently running jobs without handling output or anything. 933 * This function is to be called only in the event of a major 934 * error. 935 * 936 * Side Effects: 937 * All children are killed 938 *----------------------------------------------------------------------- 939 */ 940 void 941 Job_AbortAll(void) 942 { 943 Job *job; /* the job descriptor in that element */ 944 int foo; 945 946 aborting = ABORT_ERROR; 947 948 for (job = runningJobs; job != NULL; job = job->next) { 949 killpg(job->pid, SIGINT); 950 killpg(job->pid, SIGKILL); 951 } 952 953 /* 954 * Catch as many children as want to report in at first, then give up 955 */ 956 while (waitpid(WAIT_ANY, &foo, WNOHANG) > 0) 957 continue; 958 } 959