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