1 /* $NetBSD: job.c,v 1.492 2025/04/12 13:00:21 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright (c) 1988, 1989 by Adam de Boor 37 * Copyright (c) 1989 by Berkeley Softworks 38 * All rights reserved. 39 * 40 * This code is derived from software contributed to Berkeley by 41 * Adam de Boor. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Berkeley and its contributors. 55 * 4. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 */ 71 72 /* 73 * Create child processes and collect their output. 74 * 75 * Interface: 76 * Job_Init Called to initialize this module. In addition, 77 * the .BEGIN target is made, including all of its 78 * dependencies before this function returns. 79 * Hence, the makefiles must have been parsed 80 * before this function is called. 81 * 82 * Job_End Clean up any memory used. 83 * 84 * Job_Make Start the creation of the given target. 85 * 86 * Job_CatchChildren 87 * Check for and handle the termination of any 88 * children. This must be called reasonably 89 * frequently to keep the whole make going at 90 * a decent clip, since job table entries aren't 91 * removed until their process is caught this way. 92 * 93 * Job_CatchOutput 94 * Print any output our children have produced. 95 * Should also be called fairly frequently to 96 * keep the user informed of what's going on. 97 * If no output is waiting, it will block for 98 * a time given by the SEL_* constants, below, 99 * or until output is ready. 100 * 101 * Job_ParseShell Given a special dependency line with target '.SHELL', 102 * define the shell that is used for the creation 103 * commands in jobs mode. 104 * 105 * Job_Finish Make the .END target. Should only be called when the 106 * job table is empty. 107 * 108 * Job_AbortAll Abort all currently running jobs. Do not handle 109 * output or do anything for the jobs, just kill them. 110 * Should only be called in an emergency. 111 * 112 * Job_CheckCommands 113 * Verify that the commands for a target are 114 * ok. Provide them if necessary and possible. 115 * 116 * Job_Touch Update a target without really updating it. 117 * 118 * Job_Wait Wait for all currently-running jobs to finish. 119 */ 120 121 #ifdef HAVE_CONFIG_H 122 # include "config.h" 123 #endif 124 #include <sys/types.h> 125 #include <sys/stat.h> 126 #include <sys/file.h> 127 #include <sys/time.h> 128 #include "wait.h" 129 130 #include <errno.h> 131 #if !defined(USE_SELECT) && defined(HAVE_POLL_H) 132 #include <poll.h> 133 #else 134 #ifndef USE_SELECT /* no poll.h */ 135 # define USE_SELECT 136 #endif 137 #if defined(HAVE_SYS_SELECT_H) 138 # include <sys/select.h> 139 #endif 140 #endif 141 #include <signal.h> 142 #include <utime.h> 143 #if defined(HAVE_SYS_SOCKET_H) 144 # include <sys/socket.h> 145 #endif 146 147 #include "make.h" 148 #include "dir.h" 149 #include "job.h" 150 #include "pathnames.h" 151 #include "trace.h" 152 153 /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ 154 MAKE_RCSID("$NetBSD: job.c,v 1.492 2025/04/12 13:00:21 rillig Exp $"); 155 156 /* 157 * A shell defines how the commands are run. All commands for a target are 158 * written into a single file, which is then given to the shell to execute 159 * the commands from it. The commands are written to the file using a few 160 * templates for echo control and error control. 161 * 162 * The name of the shell is the basename for the predefined shells, such as 163 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its 164 * basename is used to select the type of shell; the longest match wins. 165 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. 166 * 167 * The echoing of command lines is controlled using hasEchoCtl, echoOff, 168 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it 169 * still outputs something, but this something is not interesting, therefore 170 * it is filtered out using noPrint and noPrintLen. 171 * 172 * The error checking for individual commands is controlled using hasErrCtl, 173 * errOn, errOff and runChkTmpl. 174 * 175 * In case a shell doesn't have error control, echoTmpl is a printf template 176 * for echoing the command, should echoing be on; runIgnTmpl is another 177 * printf template for executing the command while ignoring the return 178 * status. Finally runChkTmpl is a printf template for running the command and 179 * causing the shell to exit on error. If any of these strings are empty when 180 * hasErrCtl is false, the command will be executed anyway as is, and if it 181 * causes an error, so be it. Any templates set up to echo the command will 182 * escape any '$ ` \ "' characters in the command string to avoid unwanted 183 * shell code injection, the escaped command is safe to use in double quotes. 184 * 185 * The command-line flags "echo" and "exit" also control the behavior. The 186 * "echo" flag causes the shell to start echoing commands right away. The 187 * "exit" flag causes the shell to exit when an error is detected in one of 188 * the commands. 189 */ 190 typedef struct Shell { 191 192 /* 193 * The name of the shell. For Bourne and C shells, this is used only 194 * to find the shell description when used as the single source of a 195 * .SHELL target. For user-defined shells, this is the full path of 196 * the shell. 197 */ 198 const char *name; 199 200 bool hasEchoCtl; /* whether both echoOff and echoOn are there */ 201 const char *echoOff; /* command to turn echoing off */ 202 const char *echoOn; /* command to turn echoing back on */ 203 const char *noPrint; /* text to skip when printing output from the 204 * shell. This is usually the same as echoOff */ 205 size_t noPrintLen; /* length of noPrint command */ 206 207 bool hasErrCtl; /* whether error checking can be controlled 208 * for individual commands */ 209 const char *errOn; /* command to turn on error checking */ 210 const char *errOff; /* command to turn off error checking */ 211 212 const char *echoTmpl; /* template to echo a command */ 213 const char *runIgnTmpl; /* template to run a command without error 214 * checking */ 215 const char *runChkTmpl; /* template to run a command with error 216 * checking */ 217 218 /* 219 * A string literal that results in a newline character when it 220 * occurs outside of any 'quote' or "quote" characters. 221 */ 222 const char *newline; 223 char commentChar; /* character used by shell for comment lines */ 224 225 const char *echoFlag; /* shell flag to echo commands */ 226 const char *errFlag; /* shell flag to exit on error */ 227 } Shell; 228 229 typedef struct CommandFlags { 230 /* Whether to echo the command before or instead of running it. */ 231 bool echo; 232 233 /* Run the command even in -n or -N mode. */ 234 bool always; 235 236 /* 237 * true if we turned error checking off before writing the command to 238 * the commands file and need to turn it back on 239 */ 240 bool ignerr; 241 } CommandFlags; 242 243 /* 244 * Write shell commands to a file. 245 * 246 * TODO: keep track of whether commands are echoed. 247 * TODO: keep track of whether error checking is active. 248 */ 249 typedef struct ShellWriter { 250 FILE *f; 251 252 /* we've sent 'set -x' */ 253 bool xtraced; 254 255 } ShellWriter; 256 257 /* 258 * FreeBSD: traditionally .MAKE is not required to 259 * pass jobs queue to sub-makes. 260 * Use .MAKE.ALWAYS_PASS_JOB_QUEUE=no to disable. 261 */ 262 #define MAKE_ALWAYS_PASS_JOB_QUEUE "${.MAKE.ALWAYS_PASS_JOB_QUEUE:U}" 263 static bool Always_pass_job_queue = true; 264 /* 265 * FreeBSD: aborting entire parallel make isn't always 266 * desired. When doing tinderbox for example, failure of 267 * one architecture should not stop all. 268 * We still want to bail on interrupt though. 269 */ 270 #define MAKE_JOB_ERROR_TOKEN "${MAKE_JOB_ERROR_TOKEN:U}" 271 static bool Job_error_token = true; 272 273 /* error handling variables */ 274 static int job_errors = 0; /* number of errors reported */ 275 static enum { /* Why is the make aborting? */ 276 ABORT_NONE, 277 ABORT_ERROR, /* Aborted because of an error */ 278 ABORT_INTERRUPT, /* Aborted because it was interrupted */ 279 ABORT_WAIT /* Waiting for jobs to finish */ 280 } aborting = ABORT_NONE; 281 #define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */ 282 283 /* Tracks the number of tokens currently "out" to build jobs. */ 284 int jobTokensRunning = 0; 285 286 /* 287 * Descriptions for various shells. 288 * 289 * The build environment may set DEFSHELL_INDEX to one of 290 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to 291 * select one of the predefined shells as the default shell. 292 * 293 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the 294 * name or the full path of a sh-compatible shell, which will be used as 295 * the default shell. 296 * 297 * ".SHELL" lines in Makefiles can choose the default shell from the 298 * set defined here, or add additional shells. 299 */ 300 301 #ifdef DEFSHELL_CUSTOM 302 #define DEFSHELL_INDEX_CUSTOM 0 303 #define DEFSHELL_INDEX_SH 1 304 #define DEFSHELL_INDEX_KSH 2 305 #define DEFSHELL_INDEX_CSH 3 306 #else 307 #define DEFSHELL_INDEX_SH 0 308 #define DEFSHELL_INDEX_KSH 1 309 #define DEFSHELL_INDEX_CSH 2 310 #endif 311 312 #ifndef DEFSHELL_INDEX 313 #define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */ 314 #endif 315 316 static Shell shells[] = { 317 #ifdef DEFSHELL_CUSTOM 318 /* 319 * An sh-compatible shell with a non-standard name. 320 * 321 * Keep this in sync with the "sh" description below, but avoid 322 * non-portable features that might not be supplied by all 323 * sh-compatible shells. 324 */ 325 { 326 DEFSHELL_CUSTOM, /* .name */ 327 false, /* .hasEchoCtl */ 328 "", /* .echoOff */ 329 "", /* .echoOn */ 330 "", /* .noPrint */ 331 0, /* .noPrintLen */ 332 false, /* .hasErrCtl */ 333 "", /* .errOn */ 334 "", /* .errOff */ 335 "echo \"%s\"\n", /* .echoTmpl */ 336 "%s\n", /* .runIgnTmpl */ 337 "{ %s \n} || exit $?\n", /* .runChkTmpl */ 338 "'\n'", /* .newline */ 339 '#', /* .commentChar */ 340 "", /* .echoFlag */ 341 "", /* .errFlag */ 342 }, 343 #endif /* DEFSHELL_CUSTOM */ 344 /* 345 * SH description. Echo control is also possible and, under 346 * sun UNIX anyway, one can even control error checking. 347 */ 348 { 349 "sh", /* .name */ 350 false, /* .hasEchoCtl */ 351 "", /* .echoOff */ 352 "", /* .echoOn */ 353 "", /* .noPrint */ 354 0, /* .noPrintLen */ 355 false, /* .hasErrCtl */ 356 "", /* .errOn */ 357 "", /* .errOff */ 358 "echo \"%s\"\n", /* .echoTmpl */ 359 "%s\n", /* .runIgnTmpl */ 360 "{ %s \n} || exit $?\n", /* .runChkTmpl */ 361 "'\n'", /* .newline */ 362 '#', /* .commentChar*/ 363 #if defined(MAKE_NATIVE) && defined(__NetBSD__) 364 /* XXX: -q is not really echoFlag, it's more like noEchoInSysFlag. */ 365 "q", /* .echoFlag */ 366 #else 367 "", /* .echoFlag */ 368 #endif 369 "", /* .errFlag */ 370 }, 371 /* 372 * KSH description. 373 */ 374 { 375 "ksh", /* .name */ 376 true, /* .hasEchoCtl */ 377 "set +v", /* .echoOff */ 378 "set -v", /* .echoOn */ 379 "set +v", /* .noPrint */ 380 6, /* .noPrintLen */ 381 false, /* .hasErrCtl */ 382 "", /* .errOn */ 383 "", /* .errOff */ 384 "echo \"%s\"\n", /* .echoTmpl */ 385 "%s\n", /* .runIgnTmpl */ 386 "{ %s \n} || exit $?\n", /* .runChkTmpl */ 387 "'\n'", /* .newline */ 388 '#', /* .commentChar */ 389 "v", /* .echoFlag */ 390 "", /* .errFlag */ 391 }, 392 /* 393 * CSH description. The csh can do echo control by playing 394 * with the setting of the 'echo' shell variable. Sadly, 395 * however, it is unable to do error control nicely. 396 */ 397 { 398 "csh", /* .name */ 399 true, /* .hasEchoCtl */ 400 "unset verbose", /* .echoOff */ 401 "set verbose", /* .echoOn */ 402 "unset verbose", /* .noPrint */ 403 13, /* .noPrintLen */ 404 false, /* .hasErrCtl */ 405 "", /* .errOn */ 406 "", /* .errOff */ 407 "echo \"%s\"\n", /* .echoTmpl */ 408 "csh -c \"%s || exit 0\"\n", /* .runIgnTmpl */ 409 "", /* .runChkTmpl */ 410 "'\\\n'", /* .newline */ 411 '#', /* .commentChar */ 412 "v", /* .echoFlag */ 413 "e", /* .errFlag */ 414 } 415 }; 416 417 /* 418 * This is the shell to which we pass all commands in the Makefile. 419 * It is set by the Job_ParseShell function. 420 */ 421 static Shell *shell = &shells[DEFSHELL_INDEX]; 422 char *shellPath; /* full pathname of executable image */ 423 const char *shellName = NULL; /* last component of shellPath */ 424 char *shellErrFlag = NULL; 425 static char *shell_freeIt = NULL; /* Allocated memory for custom .SHELL */ 426 427 428 static Job *job_table; /* The structures that describe them */ 429 static Job *job_table_end; /* job_table + maxJobs */ 430 static bool wantToken; 431 static bool lurking_children = false; 432 static bool make_suspended = false; /* Whether we've seen a SIGTSTP (etc) */ 433 434 /* 435 * Set of descriptors of pipes connected to 436 * the output channels of children 437 */ 438 static struct pollfd *fds = NULL; 439 static Job **jobByFdIndex = NULL; 440 static nfds_t fdsLen = 0; 441 static void watchfd(Job *); 442 static void clearfd(Job *); 443 444 static char *targPrefix = NULL; /* To identify a job change in the output. */ 445 static Job tokenWaitJob; /* token wait pseudo-job */ 446 447 static Job childExitJob; /* child exit pseudo-job */ 448 #define CHILD_EXIT "." 449 #define DO_JOB_RESUME "R" 450 451 enum { 452 npseudojobs = 2 /* number of pseudo-jobs */ 453 }; 454 455 static sigset_t caught_signals; /* Set of signals we handle */ 456 static volatile sig_atomic_t caught_sigchld; 457 458 static void CollectOutput(Job *, bool); 459 static void JobInterrupt(bool, int) MAKE_ATTR_DEAD; 460 static void JobRestartJobs(void); 461 static void JobSigReset(void); 462 463 static void 464 SwitchOutputTo(GNode *gn) 465 { 466 /* The node for which output was most recently produced. */ 467 static GNode *lastNode = NULL; 468 469 if (gn == lastNode) 470 return; 471 lastNode = gn; 472 473 if (opts.maxJobs != 1 && targPrefix != NULL && targPrefix[0] != '\0') 474 (void)fprintf(stdout, "%s %s ---\n", targPrefix, gn->name); 475 } 476 477 static unsigned 478 nfds_per_job(void) 479 { 480 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 481 if (useMeta) 482 return 2; 483 #endif 484 return 1; 485 } 486 487 void 488 Job_FlagsToString(const Job *job, char *buf, size_t bufsize) 489 { 490 snprintf(buf, bufsize, "%c%c%c", 491 job->ignerr ? 'i' : '-', 492 !job->echo ? 's' : '-', 493 job->special ? 'S' : '-'); 494 } 495 496 static void 497 DumpJobs(const char *where) 498 { 499 Job *job; 500 char flags[4]; 501 502 debug_printf("job table @ %s\n", where); 503 for (job = job_table; job < job_table_end; job++) { 504 Job_FlagsToString(job, flags, sizeof flags); 505 debug_printf("job %d, status %d, flags %s, pid %d\n", 506 (int)(job - job_table), job->status, flags, job->pid); 507 } 508 } 509 510 /* 511 * Delete the target of a failed, interrupted, or otherwise 512 * unsuccessful job unless inhibited by .PRECIOUS. 513 */ 514 static void 515 JobDeleteTarget(GNode *gn) 516 { 517 const char *file; 518 519 if (gn->type & OP_JOIN) 520 return; 521 if (gn->type & OP_PHONY) 522 return; 523 if (GNode_IsPrecious(gn)) 524 return; 525 if (opts.noExecute) 526 return; 527 528 file = GNode_Path(gn); 529 if (unlink_file(file) == 0) 530 Error("*** %s removed", file); 531 } 532 533 /* 534 * JobSigLock/JobSigUnlock 535 * 536 * Signal lock routines to get exclusive access. Currently used to 537 * protect `jobs' and `stoppedJobs' list manipulations. 538 */ 539 static void 540 JobSigLock(sigset_t *omaskp) 541 { 542 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) { 543 Punt("JobSigLock: sigprocmask: %s", strerror(errno)); 544 sigemptyset(omaskp); 545 } 546 } 547 548 static void 549 JobSigUnlock(sigset_t *omaskp) 550 { 551 (void)sigprocmask(SIG_SETMASK, omaskp, NULL); 552 } 553 554 static void 555 JobCreatePipe(Job *job, int minfd) 556 { 557 int i, fd, flags; 558 int pipe_fds[2]; 559 560 if (pipe(pipe_fds) == -1) 561 Punt("Cannot create pipe: %s", strerror(errno)); 562 563 for (i = 0; i < 2; i++) { 564 /* Avoid using low-numbered fds */ 565 fd = fcntl(pipe_fds[i], F_DUPFD, minfd); 566 if (fd != -1) { 567 close(pipe_fds[i]); 568 pipe_fds[i] = fd; 569 } 570 } 571 572 job->inPipe = pipe_fds[0]; 573 job->outPipe = pipe_fds[1]; 574 575 if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1) 576 Punt("Cannot set close-on-exec: %s", strerror(errno)); 577 if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1) 578 Punt("Cannot set close-on-exec: %s", strerror(errno)); 579 580 /* 581 * We mark the input side of the pipe non-blocking; we poll(2) the 582 * pipe when we're waiting for a job token, but we might lose the 583 * race for the token when a new one becomes available, so the read 584 * from the pipe should not block. 585 */ 586 flags = fcntl(job->inPipe, F_GETFL, 0); 587 if (flags == -1) 588 Punt("Cannot get flags: %s", strerror(errno)); 589 flags |= O_NONBLOCK; 590 if (fcntl(job->inPipe, F_SETFL, flags) == -1) 591 Punt("Cannot set flags: %s", strerror(errno)); 592 } 593 594 /* Pass the signal to each running job. */ 595 static void 596 JobCondPassSig(int signo) 597 { 598 Job *job; 599 600 DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo); 601 602 for (job = job_table; job < job_table_end; job++) { 603 if (job->status != JOB_ST_RUNNING) 604 continue; 605 DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n", 606 signo, job->pid); 607 KILLPG(job->pid, signo); 608 } 609 } 610 611 /* 612 * SIGCHLD handler. 613 * 614 * Sends a token on the child exit pipe to wake us up from select()/poll(). 615 */ 616 static void 617 JobChildSig(int signo MAKE_ATTR_UNUSED) 618 { 619 caught_sigchld = 1; 620 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && 621 errno == EAGAIN) 622 continue; 623 } 624 625 626 /* Resume all stopped jobs. */ 627 static void 628 JobContinueSig(int signo MAKE_ATTR_UNUSED) 629 { 630 /* 631 * Defer sending SIGCONT to our stopped children until we return 632 * from the signal handler. 633 */ 634 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && 635 errno == EAGAIN) 636 continue; 637 } 638 639 /* 640 * Pass a signal on to all jobs, then resend to ourselves. 641 * We die by the same signal. 642 */ 643 MAKE_ATTR_DEAD static void 644 JobPassSig_int(int signo) 645 { 646 /* Run .INTERRUPT target then exit */ 647 JobInterrupt(true, signo); 648 } 649 650 /* 651 * Pass a signal on to all jobs, then resend to ourselves. 652 * We die by the same signal. 653 */ 654 MAKE_ATTR_DEAD static void 655 JobPassSig_term(int signo) 656 { 657 /* Dont run .INTERRUPT target then exit */ 658 JobInterrupt(false, signo); 659 } 660 661 static void 662 JobPassSig_suspend(int signo) 663 { 664 sigset_t nmask, omask; 665 struct sigaction act; 666 667 /* Suppress job started/continued messages */ 668 make_suspended = true; 669 670 /* Pass the signal onto every job */ 671 JobCondPassSig(signo); 672 673 /* 674 * Send ourselves the signal now we've given the message to everyone 675 * else. Note we block everything else possible while we're getting 676 * the signal. This ensures that all our jobs get continued when we 677 * wake up before we take any other signal. 678 */ 679 sigfillset(&nmask); 680 sigdelset(&nmask, signo); 681 (void)sigprocmask(SIG_SETMASK, &nmask, &omask); 682 683 act.sa_handler = SIG_DFL; 684 sigemptyset(&act.sa_mask); 685 act.sa_flags = 0; 686 (void)sigaction(signo, &act, NULL); 687 688 DEBUG1(JOB, "JobPassSig_suspend passing signal %d to self.\n", signo); 689 690 (void)kill(getpid(), signo); 691 692 /* 693 * We've been continued. 694 * 695 * A whole host of signals is going to happen! 696 * SIGCHLD for any processes that actually suspended themselves. 697 * SIGCHLD for any processes that exited while we were asleep. 698 * The SIGCONT that actually caused us to wake up. 699 * 700 * Since we defer passing the SIGCONT on to our children until 701 * the main processing loop, we can be sure that all the SIGCHLD 702 * events will have happened by then - and that the waitpid() will 703 * collect the child 'suspended' events. 704 * For correct sequencing we just need to ensure we process the 705 * waitpid() before passing on the SIGCONT. 706 * 707 * In any case nothing else is needed here. 708 */ 709 710 /* Restore handler and signal mask */ 711 act.sa_handler = JobPassSig_suspend; 712 (void)sigaction(signo, &act, NULL); 713 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 714 } 715 716 static Job * 717 JobFindPid(int pid, JobStatus status, bool isJobs) 718 { 719 Job *job; 720 721 for (job = job_table; job < job_table_end; job++) { 722 if (job->status == status && job->pid == pid) 723 return job; 724 } 725 if (DEBUG(JOB) && isJobs) 726 DumpJobs("no pid"); 727 return NULL; 728 } 729 730 /* Parse leading '@', '-' and '+', which control the exact execution mode. */ 731 static void 732 ParseCommandFlags(char **pp, CommandFlags *out_cmdFlags) 733 { 734 char *p = *pp; 735 out_cmdFlags->echo = true; 736 out_cmdFlags->ignerr = false; 737 out_cmdFlags->always = false; 738 739 for (;;) { 740 if (*p == '@') 741 out_cmdFlags->echo = DEBUG(LOUD); 742 else if (*p == '-') 743 out_cmdFlags->ignerr = true; 744 else if (*p == '+') 745 out_cmdFlags->always = true; 746 else if (!ch_isspace(*p)) 747 /* Ignore whitespace for compatibility with GNU make */ 748 break; 749 p++; 750 } 751 752 pp_skip_whitespace(&p); 753 754 *pp = p; 755 } 756 757 /* Escape a string for a double-quoted string literal in sh, csh and ksh. */ 758 static char * 759 EscapeShellDblQuot(const char *cmd) 760 { 761 size_t i, j; 762 763 /* Worst that could happen is every char needs escaping. */ 764 char *esc = bmake_malloc(strlen(cmd) * 2 + 1); 765 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) { 766 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || 767 cmd[i] == '"') 768 esc[j++] = '\\'; 769 esc[j] = cmd[i]; 770 } 771 esc[j] = '\0'; 772 773 return esc; 774 } 775 776 static void 777 ShellWriter_WriteFmt(ShellWriter *wr, const char *fmt, const char *arg) 778 { 779 DEBUG1(JOB, fmt, arg); 780 781 (void)fprintf(wr->f, fmt, arg); 782 if (wr->f == stdout) 783 (void)fflush(wr->f); 784 } 785 786 static void 787 ShellWriter_WriteLine(ShellWriter *wr, const char *line) 788 { 789 ShellWriter_WriteFmt(wr, "%s\n", line); 790 } 791 792 static void 793 ShellWriter_EchoOff(ShellWriter *wr) 794 { 795 if (shell->hasEchoCtl) 796 ShellWriter_WriteLine(wr, shell->echoOff); 797 } 798 799 static void 800 ShellWriter_EchoCmd(ShellWriter *wr, const char *escCmd) 801 { 802 ShellWriter_WriteFmt(wr, shell->echoTmpl, escCmd); 803 } 804 805 static void 806 ShellWriter_EchoOn(ShellWriter *wr) 807 { 808 if (shell->hasEchoCtl) 809 ShellWriter_WriteLine(wr, shell->echoOn); 810 } 811 812 static void 813 ShellWriter_TraceOn(ShellWriter *wr) 814 { 815 if (!wr->xtraced) { 816 ShellWriter_WriteLine(wr, "set -x"); 817 wr->xtraced = true; 818 } 819 } 820 821 static void 822 ShellWriter_ErrOff(ShellWriter *wr, bool echo) 823 { 824 if (echo) 825 ShellWriter_EchoOff(wr); 826 ShellWriter_WriteLine(wr, shell->errOff); 827 if (echo) 828 ShellWriter_EchoOn(wr); 829 } 830 831 static void 832 ShellWriter_ErrOn(ShellWriter *wr, bool echo) 833 { 834 if (echo) 835 ShellWriter_EchoOff(wr); 836 ShellWriter_WriteLine(wr, shell->errOn); 837 if (echo) 838 ShellWriter_EchoOn(wr); 839 } 840 841 /* 842 * The shell has no built-in error control, so emulate error control by 843 * enclosing each shell command in a template like "{ %s \n } || exit $?" 844 * (configurable per shell). 845 */ 846 static void 847 JobWriteSpecialsEchoCtl(Job *job, ShellWriter *wr, CommandFlags *inout_cmdFlags, 848 const char *escCmd, const char **inout_cmdTemplate) 849 { 850 /* XXX: Why is the whole job modified at this point? */ 851 job->ignerr = true; 852 853 if (job->echo && inout_cmdFlags->echo) { 854 ShellWriter_EchoOff(wr); 855 ShellWriter_EchoCmd(wr, escCmd); 856 857 /* 858 * Leave echoing off so the user doesn't see the commands 859 * for toggling the error checking. 860 */ 861 inout_cmdFlags->echo = false; 862 } 863 *inout_cmdTemplate = shell->runIgnTmpl; 864 865 /* 866 * The template runIgnTmpl already takes care of ignoring errors, 867 * so pretend error checking is still on. 868 * XXX: What effects does this have, and why is it necessary? 869 */ 870 inout_cmdFlags->ignerr = false; 871 } 872 873 static void 874 JobWriteSpecials(Job *job, ShellWriter *wr, const char *escCmd, bool run, 875 CommandFlags *inout_cmdFlags, const char **inout_cmdTemplate) 876 { 877 if (!run) 878 inout_cmdFlags->ignerr = false; 879 else if (shell->hasErrCtl) 880 ShellWriter_ErrOff(wr, job->echo && inout_cmdFlags->echo); 881 else if (shell->runIgnTmpl != NULL && shell->runIgnTmpl[0] != '\0') { 882 JobWriteSpecialsEchoCtl(job, wr, inout_cmdFlags, escCmd, 883 inout_cmdTemplate); 884 } else 885 inout_cmdFlags->ignerr = false; 886 } 887 888 /* 889 * Write a shell command to the job's commands file, to be run later. 890 * 891 * If the command starts with '@' and neither the -s nor the -n flag was 892 * given to make, stick a shell-specific echoOff command in the script. 893 * 894 * If the command starts with '-' and the shell has no error control (none 895 * of the predefined shells has that), ignore errors for the entire job. 896 * 897 * XXX: Why ignore errors for the entire job? This is even documented in the 898 * manual page, but without any rationale since there is no known rationale. 899 * 900 * XXX: The manual page says the '-' "affects the entire job", but that's not 901 * accurate. The '-' does not affect the commands before the '-'. 902 * 903 * If the command is just "...", skip all further commands of this job. These 904 * commands are attached to the .END node instead and will be run by 905 * Job_Finish after all other targets have been made. 906 */ 907 static void 908 JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd) 909 { 910 bool run; 911 912 CommandFlags cmdFlags; 913 /* Template for writing a command to the shell file */ 914 const char *cmdTemplate; 915 char *xcmd; /* The expanded command */ 916 char *xcmdStart; 917 char *escCmd; /* xcmd escaped to be used in double quotes */ 918 919 run = GNode_ShouldExecute(job->node); 920 921 xcmd = Var_SubstInTarget(ucmd, job->node); 922 /* TODO: handle errors */ 923 xcmdStart = xcmd; 924 925 cmdTemplate = "%s\n"; 926 927 ParseCommandFlags(&xcmd, &cmdFlags); 928 929 /* The '+' command flag overrides the -n or -N options. */ 930 if (cmdFlags.always && !run) { 931 /* 932 * We're not actually executing anything... 933 * but this one needs to be - use compat mode just for it. 934 */ 935 (void)Compat_RunCommand(ucmd, job->node, ln); 936 free(xcmdStart); 937 return; 938 } 939 940 /* 941 * If the shell doesn't have error control, the alternate echoing 942 * will be done (to avoid showing additional error checking code) 943 * and this needs some characters escaped. 944 */ 945 escCmd = shell->hasErrCtl ? NULL : EscapeShellDblQuot(xcmd); 946 947 if (!cmdFlags.echo) { 948 if (job->echo && run && shell->hasEchoCtl) 949 ShellWriter_EchoOff(wr); 950 else if (shell->hasErrCtl) 951 cmdFlags.echo = true; 952 } 953 954 if (cmdFlags.ignerr) { 955 JobWriteSpecials(job, wr, escCmd, run, &cmdFlags, &cmdTemplate); 956 } else { 957 958 /* 959 * If errors are being checked and the shell doesn't have 960 * error control but does supply an runChkTmpl template, then 961 * set up commands to run through it. 962 */ 963 964 if (!shell->hasErrCtl && shell->runChkTmpl != NULL && 965 shell->runChkTmpl[0] != '\0') { 966 if (job->echo && cmdFlags.echo) { 967 ShellWriter_EchoOff(wr); 968 ShellWriter_EchoCmd(wr, escCmd); 969 cmdFlags.echo = false; 970 } 971 /* 972 * If it's a comment line or blank, avoid the possible 973 * syntax error generated by "{\n} || exit $?". 974 */ 975 cmdTemplate = escCmd[0] == shell->commentChar || 976 escCmd[0] == '\0' 977 ? shell->runIgnTmpl 978 : shell->runChkTmpl; 979 cmdFlags.ignerr = false; 980 } 981 } 982 983 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0) 984 ShellWriter_TraceOn(wr); 985 986 ShellWriter_WriteFmt(wr, cmdTemplate, xcmd); 987 free(xcmdStart); 988 free(escCmd); 989 990 if (cmdFlags.ignerr) 991 ShellWriter_ErrOn(wr, cmdFlags.echo && job->echo); 992 993 if (!cmdFlags.echo) 994 ShellWriter_EchoOn(wr); 995 } 996 997 /* 998 * Write all commands to the shell file that is later executed. 999 * 1000 * The special command "..." stops writing and saves the remaining commands 1001 * to be executed later, when the target '.END' is made. 1002 * 1003 * Return whether at least one command was written to the shell file. 1004 */ 1005 static bool 1006 JobWriteCommands(Job *job) 1007 { 1008 StringListNode *ln; 1009 bool seen = false; 1010 ShellWriter wr; 1011 1012 wr.f = job->cmdFILE; 1013 wr.xtraced = false; 1014 1015 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) { 1016 const char *cmd = ln->datum; 1017 1018 if (strcmp(cmd, "...") == 0) { 1019 job->node->type |= OP_SAVE_CMDS; 1020 job->tailCmds = ln->next; 1021 break; 1022 } 1023 1024 JobWriteCommand(job, &wr, ln, ln->datum); 1025 seen = true; 1026 } 1027 1028 return seen; 1029 } 1030 1031 /* 1032 * Save the delayed commands (those after '...'), to be executed later in 1033 * the '.END' node, when everything else is done. 1034 */ 1035 static void 1036 JobSaveCommands(Job *job) 1037 { 1038 StringListNode *ln; 1039 1040 for (ln = job->tailCmds; ln != NULL; ln = ln->next) { 1041 const char *cmd = ln->datum; 1042 char *expanded_cmd; 1043 /* 1044 * XXX: This Var_Subst is only intended to expand the dynamic 1045 * variables such as .TARGET, .IMPSRC. It is not intended to 1046 * expand the other variables as well; see deptgt-end.mk. 1047 */ 1048 expanded_cmd = Var_SubstInTarget(cmd, job->node); 1049 /* TODO: handle errors */ 1050 Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd); 1051 Parse_RegisterCommand(expanded_cmd); 1052 } 1053 } 1054 1055 1056 /* Called to close both input and output pipes when a job is finished. */ 1057 static void 1058 JobClosePipes(Job *job) 1059 { 1060 clearfd(job); 1061 (void)close(job->outPipe); 1062 job->outPipe = -1; 1063 1064 CollectOutput(job, true); 1065 (void)close(job->inPipe); 1066 job->inPipe = -1; 1067 } 1068 1069 static void 1070 DebugFailedJob(const Job *job) 1071 { 1072 const StringListNode *ln; 1073 1074 if (!DEBUG(ERROR)) 1075 return; 1076 1077 debug_printf("\n"); 1078 debug_printf("*** Failed target: %s\n", job->node->name); 1079 debug_printf("*** In directory: %s\n", curdir); 1080 debug_printf("*** Failed commands:\n"); 1081 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) { 1082 const char *cmd = ln->datum; 1083 debug_printf("\t%s\n", cmd); 1084 1085 if (strchr(cmd, '$') != NULL) { 1086 char *xcmd = Var_Subst(cmd, job->node, VARE_EVAL); 1087 debug_printf("\t=> %s\n", xcmd); 1088 free(xcmd); 1089 } 1090 } 1091 } 1092 1093 static void 1094 JobFinishDoneExitedError(Job *job, WAIT_T *inout_status) 1095 { 1096 SwitchOutputTo(job->node); 1097 #ifdef USE_META 1098 if (useMeta) { 1099 meta_job_error(job, job->node, 1100 job->ignerr, WEXITSTATUS(*inout_status)); 1101 } 1102 #endif 1103 if (!shouldDieQuietly(job->node, -1)) { 1104 DebugFailedJob(job); 1105 (void)printf("*** [%s] Error code %d%s\n", 1106 job->node->name, WEXITSTATUS(*inout_status), 1107 job->ignerr ? " (ignored)" : ""); 1108 } 1109 1110 if (job->ignerr) 1111 WAIT_STATUS(*inout_status) = 0; 1112 else { 1113 if (deleteOnError) 1114 JobDeleteTarget(job->node); 1115 PrintOnError(job->node, "\n"); 1116 } 1117 } 1118 1119 static void 1120 JobFinishDoneExited(Job *job, WAIT_T *inout_status) 1121 { 1122 DEBUG2(JOB, "Process %d [%s] exited.\n", job->pid, job->node->name); 1123 1124 if (WEXITSTATUS(*inout_status) != 0) 1125 JobFinishDoneExitedError(job, inout_status); 1126 else if (DEBUG(JOB)) { 1127 SwitchOutputTo(job->node); 1128 (void)printf("*** [%s] Completed successfully\n", 1129 job->node->name); 1130 } 1131 } 1132 1133 static void 1134 JobFinishDoneSignaled(Job *job, WAIT_T status) 1135 { 1136 SwitchOutputTo(job->node); 1137 DebugFailedJob(job); 1138 (void)printf("*** [%s] Signal %d\n", job->node->name, WTERMSIG(status)); 1139 if (deleteOnError) 1140 JobDeleteTarget(job->node); 1141 } 1142 1143 static void 1144 JobFinishDone(Job *job, WAIT_T *inout_status) 1145 { 1146 if (WIFEXITED(*inout_status)) 1147 JobFinishDoneExited(job, inout_status); 1148 else 1149 JobFinishDoneSignaled(job, *inout_status); 1150 1151 (void)fflush(stdout); 1152 } 1153 1154 /* 1155 * Do final processing for the given job including updating parent nodes and 1156 * starting new jobs as available/necessary. 1157 * 1158 * Deferred commands for the job are placed on the .END node. 1159 * 1160 * If there was a serious error (job_errors != 0; not an ignored one), no more 1161 * jobs will be started. 1162 * 1163 * Input: 1164 * job job to finish 1165 * status sub-why job went away 1166 */ 1167 static void 1168 JobFinish (Job *job, WAIT_T status) 1169 { 1170 bool done, return_job_token; 1171 1172 DEBUG3(JOB, "JobFinish: %d [%s], status %d\n", 1173 job->pid, job->node->name, status); 1174 1175 if ((WIFEXITED(status) && 1176 ((WEXITSTATUS(status) != 0 && !job->ignerr))) || 1177 WIFSIGNALED(status)) { 1178 /* Finished because of an error. */ 1179 1180 JobClosePipes(job); 1181 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1182 if (fclose(job->cmdFILE) != 0) 1183 Punt("Cannot write shell script for '%s': %s", 1184 job->node->name, strerror(errno)); 1185 job->cmdFILE = NULL; 1186 } 1187 done = true; 1188 1189 } else if (WIFEXITED(status)) { 1190 /* 1191 * Deal with ignored errors in -B mode. We need to print a 1192 * message telling of the ignored error as well as to run 1193 * the next command. 1194 */ 1195 done = WEXITSTATUS(status) != 0; 1196 1197 JobClosePipes(job); 1198 1199 } else { 1200 /* No need to close things down or anything. */ 1201 done = false; 1202 } 1203 1204 if (done) 1205 JobFinishDone(job, &status); 1206 1207 #ifdef USE_META 1208 if (useMeta) { 1209 int meta_status = meta_job_finish(job); 1210 if (meta_status != 0 && status == 0) 1211 status = meta_status; 1212 } 1213 #endif 1214 1215 return_job_token = false; 1216 1217 Trace_Log(JOBEND, job); 1218 if (!job->special) { 1219 if (WAIT_STATUS(status) != 0 || 1220 (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT) 1221 return_job_token = true; 1222 } 1223 1224 if (aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT && 1225 (WAIT_STATUS(status) == 0)) { 1226 /* 1227 * As long as we aren't aborting and the job didn't return a 1228 * non-zero status that we shouldn't ignore, we call 1229 * Make_Update to update the parents. 1230 */ 1231 JobSaveCommands(job); 1232 job->node->made = MADE; 1233 if (!job->special) 1234 return_job_token = true; 1235 Make_Update(job->node); 1236 job->status = JOB_ST_FREE; 1237 } else if (status != 0) { 1238 job_errors++; 1239 job->status = JOB_ST_FREE; 1240 } 1241 1242 if (job_errors > 0 && !opts.keepgoing && aborting != ABORT_INTERRUPT) { 1243 /* Prevent more jobs from getting started. */ 1244 aborting = ABORT_ERROR; 1245 } 1246 1247 if (return_job_token) 1248 Job_TokenReturn(); 1249 1250 if (aborting == ABORT_ERROR && jobTokensRunning == 0) { 1251 if (shouldDieQuietly(NULL, -1)) { 1252 Job_Wait(); 1253 exit(2); 1254 } 1255 Fatal("%d error%s", job_errors, job_errors == 1 ? "" : "s"); 1256 } 1257 } 1258 1259 static void 1260 TouchRegular(GNode *gn) 1261 { 1262 const char *file = GNode_Path(gn); 1263 struct utimbuf times; 1264 int fd; 1265 char c; 1266 1267 times.actime = now; 1268 times.modtime = now; 1269 if (utime(file, ×) >= 0) 1270 return; 1271 1272 fd = open(file, O_RDWR | O_CREAT, 0666); 1273 if (fd < 0) { 1274 (void)fprintf(stderr, "*** couldn't touch %s: %s\n", 1275 file, strerror(errno)); 1276 (void)fflush(stderr); 1277 return; /* XXX: What about propagating the error? */ 1278 } 1279 1280 /* 1281 * Last resort: update the file's time stamps in the traditional way. 1282 * XXX: This doesn't work for empty files, which are sometimes used 1283 * as marker files. 1284 */ 1285 if (read(fd, &c, 1) == 1) { 1286 (void)lseek(fd, 0, SEEK_SET); 1287 while (write(fd, &c, 1) == -1 && errno == EAGAIN) 1288 continue; 1289 } 1290 (void)close(fd); /* XXX: What about propagating the error? */ 1291 } 1292 1293 /* 1294 * Touch the given target. Called by Job_Make when the -t flag was given. 1295 * 1296 * The modification date of the file is changed. 1297 * If the file did not exist, it is created. 1298 */ 1299 void 1300 Job_Touch(GNode *gn, bool echo) 1301 { 1302 if (gn->type & 1303 (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC | OP_OPTIONAL | 1304 OP_SPECIAL | OP_PHONY)) { 1305 /* 1306 * These are "virtual" targets and should not really be 1307 * created. 1308 */ 1309 return; 1310 } 1311 1312 if (echo || !GNode_ShouldExecute(gn)) { 1313 (void)fprintf(stdout, "touch %s\n", gn->name); 1314 (void)fflush(stdout); 1315 } 1316 1317 if (!GNode_ShouldExecute(gn)) 1318 return; 1319 1320 if (gn->type & OP_ARCHV) 1321 Arch_Touch(gn); 1322 else if (gn->type & OP_LIB) 1323 Arch_TouchLib(gn); 1324 else 1325 TouchRegular(gn); 1326 } 1327 1328 /* 1329 * Make sure the given node has all the commands it needs. 1330 * 1331 * The node will have commands from the .DEFAULT rule added to it if it 1332 * needs them. 1333 * 1334 * Input: 1335 * gn The target whose commands need verifying 1336 * abortProc Function to abort with message 1337 * 1338 * Results: 1339 * true if the commands list is/was ok. 1340 */ 1341 bool 1342 Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 1343 { 1344 if (GNode_IsTarget(gn)) 1345 return true; 1346 if (!Lst_IsEmpty(&gn->commands)) 1347 return true; 1348 if ((gn->type & OP_LIB) && !Lst_IsEmpty(&gn->children)) 1349 return true; 1350 1351 /* 1352 * No commands. Look for .DEFAULT rule from which we might infer 1353 * commands. 1354 */ 1355 if (defaultNode != NULL && !Lst_IsEmpty(&defaultNode->commands) && 1356 !(gn->type & OP_SPECIAL)) { 1357 /* 1358 * The traditional Make only looks for a .DEFAULT if the node 1359 * was never the target of an operator, so that's what we do 1360 * too. 1361 * 1362 * The .DEFAULT node acts like a transformation rule, in that 1363 * gn also inherits any attributes or sources attached to 1364 * .DEFAULT itself. 1365 */ 1366 Make_HandleUse(defaultNode, gn); 1367 Var_Set(gn, IMPSRC, GNode_VarTarget(gn)); 1368 return true; 1369 } 1370 1371 Dir_UpdateMTime(gn, false); 1372 if (gn->mtime != 0 || (gn->type & OP_SPECIAL)) 1373 return true; 1374 1375 /* 1376 * The node wasn't the target of an operator. We have no .DEFAULT 1377 * rule to go on and the target doesn't already exist. There's 1378 * nothing more we can do for this branch. If the -k flag wasn't 1379 * given, we stop in our tracks, otherwise we just don't update 1380 * this node's parents so they never get examined. 1381 */ 1382 1383 if (gn->flags.fromDepend) { 1384 if (!Job_RunTarget(".STALE", gn->fname)) 1385 fprintf(stdout, 1386 "%s: %s:%u: ignoring stale %s for %s\n", 1387 progname, gn->fname, gn->lineno, makeDependfile, 1388 gn->name); 1389 return true; 1390 } 1391 1392 if (gn->type & OP_OPTIONAL) { 1393 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1394 progname, gn->name, "ignored"); 1395 (void)fflush(stdout); 1396 return true; 1397 } 1398 1399 if (opts.keepgoing) { 1400 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1401 progname, gn->name, "continuing"); 1402 (void)fflush(stdout); 1403 return false; 1404 } 1405 1406 abortProc("don't know how to make %s. Stop", gn->name); 1407 return false; 1408 } 1409 1410 /* 1411 * Execute the shell for the given job. 1412 * 1413 * See Job_CatchOutput for handling the output of the shell. 1414 */ 1415 static void 1416 JobExec(Job *job, char **argv) 1417 { 1418 int cpid; /* ID of new child */ 1419 sigset_t mask; 1420 1421 if (DEBUG(JOB)) { 1422 int i; 1423 1424 debug_printf("Running %s\n", job->node->name); 1425 debug_printf("\tCommand: "); 1426 for (i = 0; argv[i] != NULL; i++) { 1427 debug_printf("%s ", argv[i]); 1428 } 1429 debug_printf("\n"); 1430 } 1431 1432 /* 1433 * Some jobs produce no output, and it's disconcerting to have 1434 * no feedback of their running (since they produce no output, the 1435 * banner with their name in it never appears). This is an attempt to 1436 * provide that feedback, even if nothing follows it. 1437 */ 1438 if (job->echo) 1439 SwitchOutputTo(job->node); 1440 1441 /* No interruptions until this job is on the `jobs' list */ 1442 JobSigLock(&mask); 1443 1444 /* Pre-emptively mark job running, pid still zero though */ 1445 job->status = JOB_ST_RUNNING; 1446 1447 Var_ReexportVars(job->node); 1448 1449 cpid = FORK_FUNCTION(); 1450 if (cpid == -1) 1451 Punt("Cannot fork: %s", strerror(errno)); 1452 1453 if (cpid == 0) { 1454 /* Child */ 1455 sigset_t tmask; 1456 1457 #ifdef USE_META 1458 if (useMeta) 1459 meta_job_child(job); 1460 #endif 1461 /* 1462 * Reset all signal handlers; this is necessary because we 1463 * also need to unblock signals before we exec(2). 1464 */ 1465 JobSigReset(); 1466 1467 /* Now unblock signals */ 1468 sigemptyset(&tmask); 1469 JobSigUnlock(&tmask); 1470 1471 /* 1472 * Must duplicate the input stream down to the child's input 1473 * and reset it to the beginning (again). Since the stream 1474 * was marked close-on-exec, we must clear that bit in the 1475 * new input. 1476 */ 1477 if (dup2(fileno(job->cmdFILE), STDIN_FILENO) == -1) 1478 execDie("dup2", "job->cmdFILE"); 1479 if (fcntl(STDIN_FILENO, F_SETFD, 0) == -1) 1480 execDie("fcntl clear close-on-exec", "stdin"); 1481 if (lseek(STDIN_FILENO, 0, SEEK_SET) == -1) 1482 execDie("lseek to 0", "stdin"); 1483 1484 if (Always_pass_job_queue || 1485 (job->node->type & (OP_MAKE | OP_SUBMAKE))) { 1486 /* Pass job token pipe to submakes. */ 1487 if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) 1488 execDie("clear close-on-exec", 1489 "tokenWaitJob.inPipe"); 1490 if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) 1491 execDie("clear close-on-exec", 1492 "tokenWaitJob.outPipe"); 1493 } 1494 1495 /* 1496 * Set up the child's output to be routed through the pipe 1497 * we've created for it. 1498 */ 1499 if (dup2(job->outPipe, STDOUT_FILENO) == -1) 1500 execDie("dup2", "job->outPipe"); 1501 1502 /* 1503 * The output channels are marked close on exec. This bit 1504 * was duplicated by dup2 (on some systems), so we have 1505 * to clear it before routing the shell's error output to 1506 * the same place as its standard output. 1507 */ 1508 if (fcntl(STDOUT_FILENO, F_SETFD, 0) == -1) 1509 execDie("clear close-on-exec", "stdout"); 1510 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 1511 execDie("dup2", "1, 2"); 1512 1513 /* 1514 * We want to switch the child into a different process 1515 * family so we can kill it and all its descendants in 1516 * one fell swoop, by killing its process family, but not 1517 * commit suicide. 1518 */ 1519 #if defined(HAVE_SETPGID) 1520 (void)setpgid(0, getpid()); 1521 #else 1522 # if defined(HAVE_SETSID) 1523 /* XXX: dsl - I'm sure this should be setpgrp()... */ 1524 (void)setsid(); 1525 # else 1526 (void)setpgrp(0, getpid()); 1527 # endif 1528 #endif 1529 1530 (void)execv(shellPath, argv); 1531 execDie("exec", shellPath); 1532 } 1533 1534 /* Parent, continuing after the child exec */ 1535 job->pid = cpid; 1536 1537 Trace_Log(JOBSTART, job); 1538 1539 #ifdef USE_META 1540 if (useMeta) 1541 meta_job_parent(job, cpid); 1542 #endif 1543 1544 /* 1545 * Set the current position in the buffer to the beginning 1546 * and mark another stream to watch in the outputs mask 1547 */ 1548 job->curPos = 0; 1549 1550 watchfd(job); 1551 1552 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1553 if (fclose(job->cmdFILE) != 0) 1554 Punt("Cannot write shell script for '%s': %s", 1555 job->node->name, strerror(errno)); 1556 job->cmdFILE = NULL; 1557 } 1558 1559 /* Now that the job is actually running, add it to the table. */ 1560 if (DEBUG(JOB)) { 1561 debug_printf("JobExec(%s): pid %d added to jobs table\n", 1562 job->node->name, job->pid); 1563 DumpJobs("job started"); 1564 } 1565 JobSigUnlock(&mask); 1566 } 1567 1568 /* Create the argv needed to execute the shell for a given job. */ 1569 static void 1570 JobMakeArgv(Job *job, char **argv) 1571 { 1572 int argc; 1573 static char args[10]; /* For merged arguments */ 1574 1575 argv[0] = UNCONST(shellName); 1576 argc = 1; 1577 1578 if ((shell->errFlag != NULL && shell->errFlag[0] != '-') || 1579 (shell->echoFlag != NULL && shell->echoFlag[0] != '-')) { 1580 /* 1581 * At least one of the flags doesn't have a minus before it, 1582 * so merge them together. Have to do this because the Bourne 1583 * shell thinks its second argument is a file to source. 1584 * Grrrr. Note the ten-character limitation on the combined 1585 * arguments. 1586 * 1587 * TODO: Research until when the above comments were 1588 * practically relevant. 1589 */ 1590 (void)snprintf(args, sizeof args, "-%s%s", 1591 (job->ignerr ? "" : 1592 (shell->errFlag != NULL ? shell->errFlag : "")), 1593 (!job->echo ? "" : 1594 (shell->echoFlag != NULL ? shell->echoFlag : ""))); 1595 1596 if (args[1] != '\0') { 1597 argv[argc] = args; 1598 argc++; 1599 } 1600 } else { 1601 if (!job->ignerr && shell->errFlag != NULL) { 1602 argv[argc] = UNCONST(shell->errFlag); 1603 argc++; 1604 } 1605 if (job->echo && shell->echoFlag != NULL) { 1606 argv[argc] = UNCONST(shell->echoFlag); 1607 argc++; 1608 } 1609 } 1610 argv[argc] = NULL; 1611 } 1612 1613 static void 1614 JobWriteShellCommands(Job *job, GNode *gn, bool *out_run) 1615 { 1616 /* 1617 * tfile is the name of a file into which all shell commands 1618 * are put. It is removed before the child shell is executed, 1619 * unless DEBUG(SCRIPT) is set. 1620 */ 1621 char tfile[MAXPATHLEN]; 1622 int tfd; /* File descriptor to the temp file */ 1623 1624 tfd = Job_TempFile(TMPPAT, tfile, sizeof tfile); 1625 1626 job->cmdFILE = fdopen(tfd, "w+"); 1627 if (job->cmdFILE == NULL) 1628 Punt("Could not fdopen %s", tfile); 1629 1630 (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC); 1631 1632 #ifdef USE_META 1633 if (useMeta) { 1634 meta_job_start(job, gn); 1635 if (gn->type & OP_SILENT) /* might have changed */ 1636 job->echo = false; 1637 } 1638 #endif 1639 1640 *out_run = JobWriteCommands(job); 1641 } 1642 1643 void 1644 Job_Make(GNode *gn) 1645 { 1646 Job *job; /* new job descriptor */ 1647 char *argv[10]; /* Argument vector to shell */ 1648 bool cmdsOK; /* true if the nodes commands were all right */ 1649 bool run; 1650 1651 for (job = job_table; job < job_table_end; job++) { 1652 if (job->status == JOB_ST_FREE) 1653 break; 1654 } 1655 if (job >= job_table_end) 1656 Punt("Job_Make no job slots vacant"); 1657 1658 memset(job, 0, sizeof *job); 1659 job->node = gn; 1660 job->tailCmds = NULL; 1661 job->status = JOB_ST_SET_UP; 1662 1663 job->special = (gn->type & OP_SPECIAL) != OP_NONE; 1664 job->ignerr = opts.ignoreErrors || gn->type & OP_IGNORE; 1665 job->echo = !(opts.silent || gn->type & OP_SILENT); 1666 1667 /* 1668 * Check the commands now so any attributes from .DEFAULT have a 1669 * chance to migrate to the node. 1670 */ 1671 cmdsOK = Job_CheckCommands(gn, Error); 1672 1673 job->inPollfd = NULL; 1674 1675 if (Lst_IsEmpty(&gn->commands)) { 1676 job->cmdFILE = stdout; 1677 run = false; 1678 1679 /* 1680 * We're serious here, but if the commands were bogus, we're 1681 * also dead... 1682 */ 1683 if (!cmdsOK) { 1684 PrintOnError(gn, "\n"); /* provide some clue */ 1685 DieHorribly(); 1686 } 1687 } else if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) || 1688 (!opts.noExecute && !opts.touch)) { 1689 /* 1690 * The above condition looks very similar to 1691 * GNode_ShouldExecute but is subtly different. It prevents 1692 * that .MAKE targets are touched since these are usually 1693 * virtual targets. 1694 */ 1695 1696 int parseErrorsBefore; 1697 1698 /* 1699 * We're serious here, but if the commands were bogus, we're 1700 * also dead... 1701 */ 1702 if (!cmdsOK) { 1703 PrintOnError(gn, "\n"); /* provide some clue */ 1704 DieHorribly(); 1705 } 1706 1707 parseErrorsBefore = parseErrors; 1708 JobWriteShellCommands(job, gn, &run); 1709 if (parseErrors != parseErrorsBefore) 1710 run = false; 1711 (void)fflush(job->cmdFILE); 1712 } else if (!GNode_ShouldExecute(gn)) { 1713 /* 1714 * Just write all the commands to stdout in one fell swoop. 1715 * This still sets up job->tailCmds correctly. 1716 */ 1717 SwitchOutputTo(gn); 1718 job->cmdFILE = stdout; 1719 if (cmdsOK) 1720 JobWriteCommands(job); 1721 run = false; 1722 (void)fflush(job->cmdFILE); 1723 } else { 1724 Job_Touch(gn, job->echo); 1725 run = false; 1726 } 1727 1728 /* If we're not supposed to execute a shell, don't. */ 1729 if (!run) { 1730 if (!job->special) 1731 Job_TokenReturn(); 1732 /* Unlink and close the command file if we opened one */ 1733 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1734 (void)fclose(job->cmdFILE); 1735 job->cmdFILE = NULL; 1736 } 1737 1738 /* 1739 * We only want to work our way up the graph if we aren't 1740 * here because the commands for the job were no good. 1741 */ 1742 if (cmdsOK && aborting == ABORT_NONE) { 1743 JobSaveCommands(job); 1744 job->node->made = MADE; 1745 Make_Update(job->node); 1746 } 1747 job->status = JOB_ST_FREE; 1748 return; 1749 } 1750 1751 /* 1752 * Set up the control arguments to the shell. This is based on the 1753 * flags set earlier for this job. 1754 */ 1755 JobMakeArgv(job, argv); 1756 1757 /* Create the pipe by which we'll get the shell's output. */ 1758 JobCreatePipe(job, 3); 1759 1760 JobExec(job, argv); 1761 } 1762 1763 /* 1764 * If the shell has an output filter (which only csh and ksh have by default), 1765 * print the output of the child process, skipping the noPrint text of the 1766 * shell. 1767 * 1768 * Return the part of the output that the calling function needs to output by 1769 * itself. 1770 */ 1771 static char * 1772 PrintFilteredOutput(char *p, const char *endp) /* XXX: p should be const */ 1773 { 1774 char *ep; /* XXX: should be const */ 1775 1776 if (shell->noPrint == NULL || shell->noPrint[0] == '\0') 1777 return p; 1778 1779 /* 1780 * XXX: What happens if shell->noPrint occurs on the boundary of 1781 * the buffer? To work correctly in all cases, this should rather 1782 * be a proper stream filter instead of doing string matching on 1783 * selected chunks of the output. 1784 */ 1785 while ((ep = strstr(p, shell->noPrint)) != NULL) { 1786 if (ep != p) { 1787 *ep = '\0'; /* XXX: avoid writing to the buffer */ 1788 /* 1789 * The only way there wouldn't be a newline after 1790 * this line is if it were the last in the buffer. 1791 * however, since the noPrint output comes after it, 1792 * there must be a newline, so we don't print one. 1793 */ 1794 /* XXX: What about null bytes in the output? */ 1795 (void)fprintf(stdout, "%s", p); 1796 (void)fflush(stdout); 1797 } 1798 p = ep + shell->noPrintLen; 1799 if (p == endp) 1800 break; 1801 p++; /* skip over the (XXX: assumed) newline */ 1802 pp_skip_whitespace(&p); 1803 } 1804 return p; 1805 } 1806 1807 /* 1808 * This function is called whenever there is something to read on the pipe. 1809 * We collect more output from the given job and store it in the job's 1810 * outBuf. If this makes up a line, we print it tagged by the job's 1811 * identifier, as necessary. 1812 * 1813 * In the output of the shell, the 'noPrint' lines are removed. If the 1814 * command is not alone on the line (the character after it is not \0 or 1815 * \n), we do print whatever follows it. 1816 * 1817 * Input: 1818 * job the job whose output needs printing 1819 * finish true if this is the last time we'll be called 1820 * for this job 1821 */ 1822 static void 1823 CollectOutput(Job *job, bool finish) 1824 { 1825 bool gotNL; /* true if got a newline */ 1826 bool fbuf; /* true if our buffer filled up */ 1827 size_t nr; /* number of bytes read */ 1828 size_t i; /* auxiliary index into outBuf */ 1829 size_t max; /* limit for i (end of current data) */ 1830 ssize_t nRead; /* (Temporary) number of bytes read */ 1831 1832 /* Read as many bytes as will fit in the buffer. */ 1833 again: 1834 gotNL = false; 1835 fbuf = false; 1836 1837 nRead = read(job->inPipe, &job->outBuf[job->curPos], 1838 JOB_BUFSIZE - job->curPos); 1839 if (nRead < 0) { 1840 if (errno == EAGAIN) 1841 return; 1842 if (DEBUG(JOB)) 1843 perror("CollectOutput(piperead)"); 1844 nr = 0; 1845 } else 1846 nr = (size_t)nRead; 1847 1848 if (nr == 0) 1849 finish = false; /* stop looping */ 1850 1851 /* 1852 * If we hit the end-of-file (the job is dead), we must flush its 1853 * remaining output, so pretend we read a newline if there's any 1854 * output remaining in the buffer. 1855 */ 1856 if (nr == 0 && job->curPos != 0) { 1857 job->outBuf[job->curPos] = '\n'; 1858 nr = 1; 1859 } 1860 1861 max = job->curPos + nr; 1862 for (i = job->curPos; i < max; i++) 1863 if (job->outBuf[i] == '\0') 1864 job->outBuf[i] = ' '; 1865 1866 /* Look for the last newline in the bytes we just got. */ 1867 for (i = job->curPos + nr - 1; 1868 i >= job->curPos && i != (size_t)-1; i--) { 1869 if (job->outBuf[i] == '\n') { 1870 gotNL = true; 1871 break; 1872 } 1873 } 1874 1875 if (!gotNL) { 1876 job->curPos += nr; 1877 if (job->curPos == JOB_BUFSIZE) { 1878 /* 1879 * If we've run out of buffer space, we have no choice 1880 * but to print the stuff. sigh. 1881 */ 1882 fbuf = true; 1883 i = job->curPos; 1884 } 1885 } 1886 if (gotNL || fbuf) { 1887 /* 1888 * Need to send the output to the screen. Null terminate it 1889 * first, overwriting the newline character if there was one. 1890 * So long as the line isn't one we should filter (according 1891 * to the shell description), we print the line, preceded 1892 * by a target banner if this target isn't the same as the 1893 * one for which we last printed something. 1894 * The rest of the data in the buffer are then shifted down 1895 * to the start of the buffer and curPos is set accordingly. 1896 */ 1897 job->outBuf[i] = '\0'; 1898 if (i >= job->curPos) { 1899 char *p; 1900 1901 /* 1902 * FIXME: SwitchOutputTo should be here, according to 1903 * the comment above. But since PrintOutput does not 1904 * do anything in the default shell, this bug has gone 1905 * unnoticed until now. 1906 */ 1907 p = PrintFilteredOutput(job->outBuf, &job->outBuf[i]); 1908 1909 /* 1910 * There's still more in the output buffer. This time, 1911 * though, we know there's no newline at the end, so 1912 * we add one of our own free will. 1913 */ 1914 if (*p != '\0') { 1915 if (!opts.silent) 1916 SwitchOutputTo(job->node); 1917 #ifdef USE_META 1918 if (useMeta) { 1919 meta_job_output(job, p, 1920 gotNL ? "\n" : ""); 1921 } 1922 #endif 1923 (void)fprintf(stdout, "%s%s", p, 1924 gotNL ? "\n" : ""); 1925 (void)fflush(stdout); 1926 } 1927 } 1928 /* 1929 * max is the last offset still in the buffer. Move any 1930 * remaining characters to the start of the buffer and 1931 * update the end marker curPos. 1932 */ 1933 if (i < max) { 1934 (void)memmove(job->outBuf, &job->outBuf[i + 1], 1935 max - (i + 1)); 1936 job->curPos = max - (i + 1); 1937 } else { 1938 assert(i == max); 1939 job->curPos = 0; 1940 } 1941 } 1942 if (finish) { 1943 /* 1944 * If the finish flag is true, we must loop until we hit 1945 * end-of-file on the pipe. This is guaranteed to happen 1946 * eventually since the other end of the pipe is now closed 1947 * (we closed it explicitly and the child has exited). When 1948 * we do get an EOF, finish will be set false and we'll fall 1949 * through and out. 1950 */ 1951 goto again; 1952 } 1953 } 1954 1955 static void 1956 JobRun(GNode *targ) 1957 { 1958 /* Don't let these special jobs overlap with other unrelated jobs. */ 1959 Compat_Make(targ, targ); 1960 if (GNode_IsError(targ)) { 1961 PrintOnError(targ, "\n\nStop.\n"); 1962 exit(1); 1963 } 1964 } 1965 1966 void 1967 Job_CatchChildren(void) 1968 { 1969 int pid; 1970 WAIT_T status; 1971 1972 if (jobTokensRunning == 0) 1973 return; 1974 if (caught_sigchld == 0) 1975 return; 1976 caught_sigchld = 0; 1977 1978 while ((pid = waitpid((pid_t)-1, &status, WNOHANG | WUNTRACED)) > 0) { 1979 DEBUG2(JOB, "Process %d exited/stopped status %x.\n", 1980 pid, WAIT_STATUS(status)); 1981 JobReapChild(pid, status, true); 1982 } 1983 } 1984 1985 /* 1986 * It is possible that wait[pid]() was called from elsewhere, 1987 * this lets us reap jobs regardless. 1988 */ 1989 void 1990 JobReapChild(pid_t pid, WAIT_T status, bool isJobs) 1991 { 1992 Job *job; 1993 1994 if (jobTokensRunning == 0) 1995 return; 1996 1997 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); 1998 if (job == NULL) { 1999 if (isJobs && !lurking_children) 2000 Error("Child (%d) status %x not in table?", 2001 pid, status); 2002 return; 2003 } 2004 2005 if (WIFSTOPPED(status)) { 2006 DEBUG2(JOB, "Process %d (%s) stopped.\n", 2007 job->pid, job->node->name); 2008 if (!make_suspended) { 2009 switch (WSTOPSIG(status)) { 2010 case SIGTSTP: 2011 (void)printf("*** [%s] Suspended\n", 2012 job->node->name); 2013 break; 2014 case SIGSTOP: 2015 (void)printf("*** [%s] Stopped\n", 2016 job->node->name); 2017 break; 2018 default: 2019 (void)printf("*** [%s] Stopped -- signal %d\n", 2020 job->node->name, WSTOPSIG(status)); 2021 } 2022 job->suspended = true; 2023 } 2024 (void)fflush(stdout); 2025 return; 2026 } 2027 2028 job->status = JOB_ST_FINISHED; 2029 job->exit_status = WAIT_STATUS(status); 2030 if (WIFEXITED(status)) 2031 job->node->exit_status = WEXITSTATUS(status); 2032 2033 JobFinish(job, status); 2034 } 2035 2036 void 2037 Job_CatchOutput(void) 2038 { 2039 int nready; 2040 Job *job; 2041 unsigned int i; 2042 2043 (void)fflush(stdout); 2044 2045 do { 2046 /* Maybe skip the job token pipe. */ 2047 nfds_t skip = wantToken ? 0 : 1; 2048 nready = poll(fds + skip, fdsLen - skip, POLL_MSEC); 2049 } while (nready < 0 && errno == EINTR); 2050 2051 if (nready < 0) 2052 Punt("poll: %s", strerror(errno)); 2053 2054 if (nready > 0 && childExitJob.inPollfd->revents & POLLIN) { 2055 char token; 2056 ssize_t count = read(childExitJob.inPipe, &token, 1); 2057 if (count == 1) { 2058 if (token == DO_JOB_RESUME[0]) 2059 /* 2060 * Complete relay requested from our SIGCONT 2061 * handler. 2062 */ 2063 JobRestartJobs(); 2064 } else if (count == 0) 2065 Punt("unexpected eof on token pipe"); 2066 else if (errno != EAGAIN) 2067 Punt("token pipe read: %s", strerror(errno)); 2068 nready--; 2069 } 2070 2071 Job_CatchChildren(); 2072 if (nready == 0) 2073 return; 2074 2075 for (i = npseudojobs * nfds_per_job(); i < fdsLen; i++) { 2076 if (fds[i].revents == 0) 2077 continue; 2078 job = jobByFdIndex[i]; 2079 if (job->status == JOB_ST_RUNNING) 2080 CollectOutput(job, false); 2081 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2082 /* 2083 * With meta mode, we may have activity on the job's filemon 2084 * descriptor too, which at the moment is any pollfd other 2085 * than job->inPollfd. 2086 */ 2087 if (useMeta && job->inPollfd != &fds[i]) { 2088 if (meta_job_event(job) <= 0) 2089 fds[i].events = 0; /* never mind */ 2090 } 2091 #endif 2092 if (--nready == 0) 2093 return; 2094 } 2095 } 2096 2097 static void 2098 InitShellNameAndPath(void) 2099 { 2100 shellName = shell->name; 2101 2102 #ifdef DEFSHELL_CUSTOM 2103 if (shellName[0] == '/') { 2104 shellPath = bmake_strdup(shellName); 2105 shellName = str_basename(shellPath); 2106 return; 2107 } 2108 #endif 2109 #ifdef DEFSHELL_PATH 2110 shellPath = bmake_strdup(DEFSHELL_PATH); 2111 #else 2112 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName); 2113 #endif 2114 } 2115 2116 void 2117 Shell_Init(void) 2118 { 2119 if (shellPath == NULL) 2120 InitShellNameAndPath(); 2121 2122 Var_SetWithFlags(SCOPE_CMDLINE, ".SHELL", shellPath, 2123 VAR_SET_INTERNAL|VAR_SET_READONLY); 2124 if (shell->errFlag == NULL) 2125 shell->errFlag = ""; 2126 if (shell->echoFlag == NULL) 2127 shell->echoFlag = ""; 2128 if (shell->hasErrCtl && shell->errFlag[0] != '\0') { 2129 if (shellErrFlag != NULL && 2130 strcmp(shell->errFlag, &shellErrFlag[1]) != 0) { 2131 free(shellErrFlag); 2132 shellErrFlag = NULL; 2133 } 2134 if (shellErrFlag == NULL) 2135 shellErrFlag = str_concat2("-", shell->errFlag); 2136 } else if (shellErrFlag != NULL) { 2137 free(shellErrFlag); 2138 shellErrFlag = NULL; 2139 } 2140 } 2141 2142 /* Return the shell string literal that results in a newline character. */ 2143 const char * 2144 Shell_GetNewline(void) 2145 { 2146 return shell->newline; 2147 } 2148 2149 void 2150 Job_SetPrefix(void) 2151 { 2152 if (targPrefix != NULL) 2153 free(targPrefix); 2154 else if (!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOB.PREFIX")) 2155 Global_Set(".MAKE.JOB.PREFIX", "---"); 2156 2157 targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}", 2158 SCOPE_GLOBAL, VARE_EVAL); 2159 /* TODO: handle errors */ 2160 } 2161 2162 static void 2163 AddSig(int sig, SignalProc handler) 2164 { 2165 if (bmake_signal(sig, SIG_IGN) != SIG_IGN) { 2166 sigaddset(&caught_signals, sig); 2167 (void)bmake_signal(sig, handler); 2168 } 2169 } 2170 2171 void 2172 Job_Init(void) 2173 { 2174 Job_SetPrefix(); 2175 2176 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); 2177 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); 2178 job_table_end = job_table + opts.maxJobs; 2179 wantToken = false; 2180 caught_sigchld = 0; 2181 2182 aborting = ABORT_NONE; 2183 job_errors = 0; 2184 2185 Always_pass_job_queue = GetBooleanExpr(MAKE_ALWAYS_PASS_JOB_QUEUE, 2186 Always_pass_job_queue); 2187 2188 Job_error_token = GetBooleanExpr(MAKE_JOB_ERROR_TOKEN, Job_error_token); 2189 2190 2191 /* 2192 * There is a non-zero chance that we already have children, 2193 * e.g. after 'make -f- <<EOF'. 2194 * Since their termination causes a 'Child (pid) not in table' 2195 * message, Collect the status of any that are already dead, and 2196 * suppress the error message if there are any undead ones. 2197 */ 2198 for (;;) { 2199 int rval; 2200 WAIT_T status; 2201 2202 rval = waitpid((pid_t)-1, &status, WNOHANG); 2203 if (rval > 0) 2204 continue; 2205 if (rval == 0) 2206 lurking_children = true; 2207 break; 2208 } 2209 2210 Shell_Init(); 2211 2212 JobCreatePipe(&childExitJob, 3); 2213 2214 { 2215 size_t nfds = (npseudojobs + (size_t)opts.maxJobs) * 2216 nfds_per_job(); 2217 fds = bmake_malloc(sizeof *fds * nfds); 2218 jobByFdIndex = bmake_malloc(sizeof *jobByFdIndex * nfds); 2219 } 2220 2221 /* These are permanent entries and take slots 0 and 1 */ 2222 watchfd(&tokenWaitJob); 2223 watchfd(&childExitJob); 2224 2225 sigemptyset(&caught_signals); 2226 (void)bmake_signal(SIGCHLD, JobChildSig); 2227 sigaddset(&caught_signals, SIGCHLD); 2228 2229 /* Handle the signals specified by POSIX. */ 2230 AddSig(SIGINT, JobPassSig_int); 2231 AddSig(SIGHUP, JobPassSig_term); 2232 AddSig(SIGTERM, JobPassSig_term); 2233 AddSig(SIGQUIT, JobPassSig_term); 2234 2235 /* 2236 * These signals need to be passed to the jobs, as each job has its 2237 * own process group and thus the terminal driver doesn't forward the 2238 * signals itself. 2239 */ 2240 AddSig(SIGTSTP, JobPassSig_suspend); 2241 AddSig(SIGTTOU, JobPassSig_suspend); 2242 AddSig(SIGTTIN, JobPassSig_suspend); 2243 AddSig(SIGWINCH, JobCondPassSig); 2244 AddSig(SIGCONT, JobContinueSig); 2245 2246 (void)Job_RunTarget(".BEGIN", NULL); 2247 /* Create the .END node, see Targ_GetEndNode in Compat_MakeAll. */ 2248 (void)Targ_GetEndNode(); 2249 } 2250 2251 static void 2252 DelSig(int sig) 2253 { 2254 if (sigismember(&caught_signals, sig) != 0) 2255 (void)bmake_signal(sig, SIG_DFL); 2256 } 2257 2258 static void 2259 JobSigReset(void) 2260 { 2261 DelSig(SIGINT); 2262 DelSig(SIGHUP); 2263 DelSig(SIGQUIT); 2264 DelSig(SIGTERM); 2265 DelSig(SIGTSTP); 2266 DelSig(SIGTTOU); 2267 DelSig(SIGTTIN); 2268 DelSig(SIGWINCH); 2269 DelSig(SIGCONT); 2270 (void)bmake_signal(SIGCHLD, SIG_DFL); 2271 } 2272 2273 static Shell * 2274 FindShellByName(const char *name) 2275 { 2276 Shell *sh = shells; 2277 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0]; 2278 2279 for (sh = shells; sh < shellsEnd; sh++) { 2280 if (strcmp(name, sh->name) == 0) 2281 return sh; 2282 } 2283 return NULL; 2284 } 2285 2286 /* 2287 * Parse a shell specification and set up 'shell', shellPath and 2288 * shellName appropriately. 2289 * 2290 * Input: 2291 * line The shell spec 2292 * 2293 * Results: 2294 * Returns false if the specification was incorrect. 2295 * If successful, 'shell' is usable, shellPath is the full path of the 2296 * shell described by 'shell', and shellName is the final component of 2297 * shellPath. 2298 * 2299 * Notes: 2300 * A shell specification has the form ".SHELL: keyword=value...". Double 2301 * quotes can be used to enclose blanks in words. A backslash escapes 2302 * anything (most notably a double-quote and a space) and 2303 * provides the usual escape sequences from C. There should be no 2304 * unnecessary spaces in the word. The keywords are: 2305 * name Name of shell. 2306 * path Location of shell. 2307 * quiet Command to turn off echoing. 2308 * echo Command to turn echoing on 2309 * filter The output from the shell command that turns off 2310 * echoing, to be filtered from the final output. 2311 * echoFlag Flag to turn echoing on at the start. 2312 * errFlag Flag to turn error checking on at the start. 2313 * hasErrCtl True if the shell has error checking control. 2314 * newline String literal to represent a newline character. 2315 * check If hasErrCtl is true: The command to turn on error 2316 * checking. If hasErrCtl is false: The template for a 2317 * shell command that echoes a command for which error 2318 * checking is off. 2319 * ignore If hasErrCtl is true: The command to turn off error 2320 * checking. If hasErrCtl is false: The template for a 2321 * shell command that executes a command so as to ignore 2322 * any errors it returns. 2323 */ 2324 bool 2325 Job_ParseShell(char *line) 2326 { 2327 Words wordsList; 2328 char **words; 2329 char **argv; 2330 size_t argc; 2331 char *path; 2332 Shell newShell; 2333 bool fullSpec = false; 2334 Shell *sh; 2335 2336 /* XXX: don't use line as an iterator variable */ 2337 pp_skip_whitespace(&line); 2338 2339 free(shell_freeIt); 2340 2341 memset(&newShell, 0, sizeof newShell); 2342 2343 wordsList = Str_Words(line, true); 2344 words = wordsList.words; 2345 argc = wordsList.len; 2346 path = wordsList.freeIt; 2347 if (words == NULL) { 2348 Error("Unterminated quoted string [%s]", line); 2349 return false; 2350 } 2351 shell_freeIt = path; 2352 2353 for (path = NULL, argv = words; argc != 0; argc--, argv++) { 2354 char *arg = *argv; 2355 if (strncmp(arg, "path=", 5) == 0) { 2356 path = arg + 5; 2357 } else if (strncmp(arg, "name=", 5) == 0) { 2358 newShell.name = arg + 5; 2359 } else { 2360 if (strncmp(arg, "quiet=", 6) == 0) { 2361 newShell.echoOff = arg + 6; 2362 } else if (strncmp(arg, "echo=", 5) == 0) { 2363 newShell.echoOn = arg + 5; 2364 } else if (strncmp(arg, "filter=", 7) == 0) { 2365 newShell.noPrint = arg + 7; 2366 newShell.noPrintLen = strlen(newShell.noPrint); 2367 } else if (strncmp(arg, "echoFlag=", 9) == 0) { 2368 newShell.echoFlag = arg + 9; 2369 } else if (strncmp(arg, "errFlag=", 8) == 0) { 2370 newShell.errFlag = arg + 8; 2371 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) { 2372 char c = arg[10]; 2373 newShell.hasErrCtl = c == 'Y' || c == 'y' || 2374 c == 'T' || c == 't'; 2375 } else if (strncmp(arg, "newline=", 8) == 0) { 2376 newShell.newline = arg + 8; 2377 } else if (strncmp(arg, "check=", 6) == 0) { 2378 /* 2379 * Before 2020-12-10, these two variables had 2380 * been a single variable. 2381 */ 2382 newShell.errOn = arg + 6; 2383 newShell.echoTmpl = arg + 6; 2384 } else if (strncmp(arg, "ignore=", 7) == 0) { 2385 /* 2386 * Before 2020-12-10, these two variables had 2387 * been a single variable. 2388 */ 2389 newShell.errOff = arg + 7; 2390 newShell.runIgnTmpl = arg + 7; 2391 } else if (strncmp(arg, "errout=", 7) == 0) { 2392 newShell.runChkTmpl = arg + 7; 2393 } else if (strncmp(arg, "comment=", 8) == 0) { 2394 newShell.commentChar = arg[8]; 2395 } else { 2396 Parse_Error(PARSE_FATAL, 2397 "Unknown keyword \"%s\"", arg); 2398 free(words); 2399 return false; 2400 } 2401 fullSpec = true; 2402 } 2403 } 2404 2405 if (path == NULL) { 2406 if (newShell.name == NULL) { 2407 Parse_Error(PARSE_FATAL, 2408 "Neither path nor name specified"); 2409 free(words); 2410 return false; 2411 } else { 2412 if ((sh = FindShellByName(newShell.name)) == NULL) { 2413 Parse_Error(PARSE_WARNING, 2414 "%s: No matching shell", newShell.name); 2415 free(words); 2416 return false; 2417 } 2418 shell = sh; 2419 shellName = newShell.name; 2420 if (shellPath != NULL) { 2421 free(shellPath); 2422 shellPath = NULL; 2423 Shell_Init(); 2424 } 2425 } 2426 } else { 2427 free(shellPath); 2428 shellPath = bmake_strdup(path); 2429 shellName = newShell.name != NULL ? newShell.name 2430 : str_basename(path); 2431 if (!fullSpec) { 2432 if ((sh = FindShellByName(shellName)) == NULL) { 2433 Parse_Error(PARSE_WARNING, 2434 "%s: No matching shell", shellName); 2435 free(words); 2436 return false; 2437 } 2438 shell = sh; 2439 } else { 2440 shell = bmake_malloc(sizeof *shell); 2441 *shell = newShell; 2442 } 2443 /* This will take care of shellErrFlag. */ 2444 Shell_Init(); 2445 } 2446 2447 if (shell->echoOn != NULL && shell->echoOff != NULL) 2448 shell->hasEchoCtl = true; 2449 2450 if (!shell->hasErrCtl) { 2451 if (shell->echoTmpl == NULL) 2452 shell->echoTmpl = ""; 2453 if (shell->runIgnTmpl == NULL) 2454 shell->runIgnTmpl = "%s\n"; 2455 } 2456 2457 /* 2458 * Do not free up the words themselves, since they may be in use 2459 * by the shell specification. 2460 */ 2461 free(words); 2462 return true; 2463 } 2464 2465 /* 2466 * After receiving an interrupt signal, terminate all child processes and if 2467 * necessary make the .INTERRUPT target. 2468 */ 2469 static void 2470 JobInterrupt(bool runINTERRUPT, int signo) 2471 { 2472 Job *job; 2473 GNode *interrupt; 2474 sigset_t mask; 2475 2476 aborting = ABORT_INTERRUPT; 2477 2478 JobSigLock(&mask); 2479 2480 for (job = job_table; job < job_table_end; job++) { 2481 if (job->status == JOB_ST_RUNNING && job->pid != 0) { 2482 DEBUG2(JOB, 2483 "JobInterrupt passing signal %d to child %d.\n", 2484 signo, job->pid); 2485 KILLPG(job->pid, signo); 2486 } 2487 } 2488 2489 for (job = job_table; job < job_table_end; job++) { 2490 if (job->status == JOB_ST_RUNNING && job->pid != 0) { 2491 int status; 2492 (void)waitpid(job->pid, &status, 0); 2493 JobDeleteTarget(job->node); 2494 } 2495 } 2496 2497 JobSigUnlock(&mask); 2498 2499 if (runINTERRUPT && !opts.touch) { 2500 interrupt = Targ_FindNode(".INTERRUPT"); 2501 if (interrupt != NULL) { 2502 opts.ignoreErrors = false; 2503 JobRun(interrupt); 2504 } 2505 } 2506 Trace_Log(MAKEINTR, NULL); 2507 exit(signo); /* XXX: why signo? */ 2508 } 2509 2510 /* Make the .END target, returning the number of job-related errors. */ 2511 int 2512 Job_Finish(void) 2513 { 2514 GNode *endNode = Targ_GetEndNode(); 2515 if (!Lst_IsEmpty(&endNode->commands) || 2516 !Lst_IsEmpty(&endNode->children)) { 2517 if (job_errors != 0) 2518 Error("Errors reported so .END ignored"); 2519 else 2520 JobRun(endNode); 2521 } 2522 return job_errors; 2523 } 2524 2525 #ifdef CLEANUP 2526 void 2527 Job_End(void) 2528 { 2529 free(shell_freeIt); 2530 } 2531 #endif 2532 2533 /* Waits for all running jobs to finish. */ 2534 void 2535 Job_Wait(void) 2536 { 2537 aborting = ABORT_WAIT; /* Prevent other jobs from starting. */ 2538 while (jobTokensRunning != 0) { 2539 Job_CatchOutput(); 2540 } 2541 aborting = ABORT_NONE; 2542 } 2543 2544 /* 2545 * Abort all currently running jobs without handling output or anything. 2546 * This function is to be called only in the event of a major error. 2547 * Most definitely NOT to be called from JobInterrupt. 2548 */ 2549 void 2550 Job_AbortAll(void) 2551 { 2552 Job *job; 2553 WAIT_T status; 2554 2555 aborting = ABORT_ERROR; 2556 2557 if (jobTokensRunning != 0) { 2558 for (job = job_table; job < job_table_end; job++) { 2559 if (job->status != JOB_ST_RUNNING) 2560 continue; 2561 KILLPG(job->pid, SIGINT); 2562 KILLPG(job->pid, SIGKILL); 2563 } 2564 } 2565 2566 while (waitpid((pid_t)-1, &status, WNOHANG) > 0) 2567 continue; 2568 } 2569 2570 /* 2571 * Tries to restart stopped jobs if there are slots available. 2572 * Called in response to a SIGCONT. 2573 */ 2574 static void 2575 JobRestartJobs(void) 2576 { 2577 Job *job; 2578 2579 for (job = job_table; job < job_table_end; job++) { 2580 if (job->status == JOB_ST_RUNNING && 2581 (make_suspended || job->suspended)) { 2582 DEBUG1(JOB, "Restarting stopped job pid %d.\n", 2583 job->pid); 2584 if (job->suspended) { 2585 (void)printf("*** [%s] Continued\n", 2586 job->node->name); 2587 (void)fflush(stdout); 2588 } 2589 job->suspended = false; 2590 if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) { 2591 debug_printf("Failed to send SIGCONT to %d\n", 2592 job->pid); 2593 } 2594 } 2595 if (job->status == JOB_ST_FINISHED) { 2596 /* 2597 * Job exit deferred after calling waitpid() in a 2598 * signal handler 2599 */ 2600 JobFinish(job, job->exit_status); 2601 } 2602 } 2603 make_suspended = false; 2604 } 2605 2606 static void 2607 watchfd(Job *job) 2608 { 2609 if (job->inPollfd != NULL) 2610 Punt("Watching watched job"); 2611 2612 fds[fdsLen].fd = job->inPipe; 2613 fds[fdsLen].events = POLLIN; 2614 jobByFdIndex[fdsLen] = job; 2615 job->inPollfd = &fds[fdsLen]; 2616 fdsLen++; 2617 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2618 if (useMeta) { 2619 fds[fdsLen].fd = meta_job_fd(job); 2620 fds[fdsLen].events = fds[fdsLen].fd == -1 ? 0 : POLLIN; 2621 jobByFdIndex[fdsLen] = job; 2622 fdsLen++; 2623 } 2624 #endif 2625 } 2626 2627 static void 2628 clearfd(Job *job) 2629 { 2630 size_t i; 2631 if (job->inPollfd == NULL) 2632 Punt("Unwatching unwatched job"); 2633 i = (size_t)(job->inPollfd - fds); 2634 fdsLen--; 2635 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2636 if (useMeta) { 2637 assert(nfds_per_job() == 2); 2638 if (i % 2 != 0) 2639 Punt("odd-numbered fd with meta"); 2640 fdsLen--; 2641 } 2642 #endif 2643 /* Move last job in table into hole made by dead job. */ 2644 if (fdsLen != i) { 2645 fds[i] = fds[fdsLen]; 2646 jobByFdIndex[i] = jobByFdIndex[fdsLen]; 2647 jobByFdIndex[i]->inPollfd = &fds[i]; 2648 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2649 if (useMeta) { 2650 fds[i + 1] = fds[fdsLen + 1]; 2651 jobByFdIndex[i + 1] = jobByFdIndex[fdsLen + 1]; 2652 } 2653 #endif 2654 } 2655 job->inPollfd = NULL; 2656 } 2657 2658 /* 2659 * Put a token (back) into the job pipe. 2660 * This allows a make process to start a build job. 2661 */ 2662 static void 2663 JobTokenAdd(void) 2664 { 2665 char tok = JOB_TOKENS[aborting], tok1; 2666 2667 if (!Job_error_token && aborting == ABORT_ERROR) { 2668 if (jobTokensRunning == 0) 2669 return; 2670 tok = '+'; /* no error token */ 2671 } 2672 2673 /* If we are depositing an error token, flush everything else. */ 2674 while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1) 2675 continue; 2676 2677 DEBUG3(JOB, "(%d) aborting %d, deposit token %c\n", 2678 getpid(), aborting, tok); 2679 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) 2680 continue; 2681 } 2682 2683 int 2684 Job_TempFile(const char *pattern, char *tfile, size_t tfile_sz) 2685 { 2686 int fd; 2687 sigset_t mask; 2688 2689 JobSigLock(&mask); 2690 fd = mkTempFile(pattern, tfile, tfile_sz); 2691 if (tfile != NULL && !DEBUG(SCRIPT)) 2692 unlink(tfile); 2693 JobSigUnlock(&mask); 2694 2695 return fd; 2696 } 2697 2698 /* Prepare the job token pipe in the root make process. */ 2699 void 2700 Job_ServerStart(int max_tokens, int jp_0, int jp_1) 2701 { 2702 int i; 2703 char jobarg[64]; 2704 2705 if (jp_0 >= 0 && jp_1 >= 0) { 2706 tokenWaitJob.inPipe = jp_0; 2707 tokenWaitJob.outPipe = jp_1; 2708 (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC); 2709 (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC); 2710 return; 2711 } 2712 2713 JobCreatePipe(&tokenWaitJob, 15); 2714 2715 snprintf(jobarg, sizeof jobarg, "%d,%d", 2716 tokenWaitJob.inPipe, tokenWaitJob.outPipe); 2717 2718 Global_Append(MAKEFLAGS, "-J"); 2719 Global_Append(MAKEFLAGS, jobarg); 2720 2721 /* 2722 * Preload the job pipe with one token per job, save the one 2723 * "extra" token for the primary job. 2724 * 2725 * XXX should clip maxJobs against PIPE_BUF -- if max_tokens is 2726 * larger than the write buffer size of the pipe, we will 2727 * deadlock here. 2728 */ 2729 for (i = 1; i < max_tokens; i++) 2730 JobTokenAdd(); 2731 } 2732 2733 /* Return a withdrawn token to the pool. */ 2734 void 2735 Job_TokenReturn(void) 2736 { 2737 jobTokensRunning--; 2738 if (jobTokensRunning < 0) 2739 Punt("token botch"); 2740 if (jobTokensRunning != 0 || JOB_TOKENS[aborting] != '+') 2741 JobTokenAdd(); 2742 } 2743 2744 /* 2745 * Attempt to withdraw a token from the pool. 2746 * 2747 * If the pool is empty, set wantToken so that we wake up when a token is 2748 * released. 2749 * 2750 * Returns true if a token was withdrawn, and false if the pool is currently 2751 * empty. 2752 */ 2753 bool 2754 Job_TokenWithdraw(void) 2755 { 2756 char tok, tok1; 2757 ssize_t count; 2758 2759 wantToken = false; 2760 DEBUG3(JOB, "Job_TokenWithdraw(%d): aborting %d, running %d\n", 2761 getpid(), aborting, jobTokensRunning); 2762 2763 if (aborting != ABORT_NONE || (jobTokensRunning >= opts.maxJobs)) 2764 return false; 2765 2766 count = read(tokenWaitJob.inPipe, &tok, 1); 2767 if (count == 0) 2768 Fatal("eof on job pipe!"); 2769 if (count < 0 && jobTokensRunning != 0) { 2770 if (errno != EAGAIN) 2771 Fatal("job pipe read: %s", strerror(errno)); 2772 DEBUG1(JOB, "(%d) blocked for token\n", getpid()); 2773 wantToken = true; 2774 return false; 2775 } 2776 2777 if (count == 1 && tok != '+') { 2778 /* make being aborted - remove any other job tokens */ 2779 DEBUG2(JOB, "(%d) aborted by token %c\n", getpid(), tok); 2780 while (read(tokenWaitJob.inPipe, &tok1, 1) == 1) 2781 continue; 2782 /* And put the stopper back */ 2783 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && 2784 errno == EAGAIN) 2785 continue; 2786 if (shouldDieQuietly(NULL, 1)) { 2787 Job_Wait(); 2788 exit(6); 2789 } 2790 Fatal("A failure has been detected " 2791 "in another branch of the parallel make"); 2792 } 2793 2794 if (count == 1 && jobTokensRunning == 0) 2795 /* We didn't want the token really */ 2796 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && 2797 errno == EAGAIN) 2798 continue; 2799 2800 jobTokensRunning++; 2801 DEBUG1(JOB, "(%d) withdrew token\n", getpid()); 2802 return true; 2803 } 2804 2805 /* Make the named target if found, exit if the target fails. */ 2806 bool 2807 Job_RunTarget(const char *target, const char *fname) 2808 { 2809 GNode *gn = Targ_FindNode(target); 2810 if (gn == NULL) 2811 return false; 2812 2813 if (fname != NULL) 2814 Var_Set(gn, ALLSRC, fname); 2815 2816 JobRun(gn); 2817 return true; 2818 } 2819 2820 #ifdef USE_SELECT 2821 int 2822 emul_poll(struct pollfd *fd, int nfd, int timeout) 2823 { 2824 fd_set rfds, wfds; 2825 int i, maxfd, nselect, npoll; 2826 struct timeval tv, *tvp; 2827 long usecs; 2828 2829 FD_ZERO(&rfds); 2830 FD_ZERO(&wfds); 2831 2832 maxfd = -1; 2833 for (i = 0; i < nfd; i++) { 2834 fd[i].revents = 0; 2835 2836 if (fd[i].events & POLLIN) 2837 FD_SET(fd[i].fd, &rfds); 2838 2839 if (fd[i].events & POLLOUT) 2840 FD_SET(fd[i].fd, &wfds); 2841 2842 if (fd[i].fd > maxfd) 2843 maxfd = fd[i].fd; 2844 } 2845 2846 if (maxfd >= FD_SETSIZE) { 2847 Punt("Ran out of fd_set slots; " 2848 "recompile with a larger FD_SETSIZE."); 2849 } 2850 2851 if (timeout < 0) { 2852 tvp = NULL; 2853 } else { 2854 usecs = timeout * 1000; 2855 tv.tv_sec = usecs / 1000000; 2856 tv.tv_usec = usecs % 1000000; 2857 tvp = &tv; 2858 } 2859 2860 nselect = select(maxfd + 1, &rfds, &wfds, NULL, tvp); 2861 2862 if (nselect <= 0) 2863 return nselect; 2864 2865 npoll = 0; 2866 for (i = 0; i < nfd; i++) { 2867 if (FD_ISSET(fd[i].fd, &rfds)) 2868 fd[i].revents |= POLLIN; 2869 2870 if (FD_ISSET(fd[i].fd, &wfds)) 2871 fd[i].revents |= POLLOUT; 2872 2873 if (fd[i].revents) 2874 npoll++; 2875 } 2876 2877 return npoll; 2878 } 2879 #endif /* USE_SELECT */ 2880