1 /* $NetBSD: job.c,v 1.519 2025/08/04 15:40:39 sjg 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.519 2025/08/04 15:40:39 sjg 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 * Write a shell command to the job's commands file, to be run later. 963 * 964 * If the command starts with '@' and neither the -s nor the -n flag was 965 * given to make, stick a shell-specific echoOff command in the script. 966 * 967 * If the command starts with '-' and the shell has no error control (none 968 * of the predefined shells has that), ignore errors for the rest of the job. 969 * 970 * XXX: Why ignore errors for the entire job? This is documented in the 971 * manual page, but without giving a rationale. 972 * 973 * If the command is just "...", attach all further commands of this job to 974 * the .END node instead, see Job_Finish. 975 */ 976 static void 977 JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd) 978 { 979 bool run; 980 981 CommandFlags cmdFlags; 982 /* Template for writing a command to the shell file */ 983 const char *cmdTemplate; 984 char *xcmd; /* The expanded command */ 985 char *xcmdStart; 986 char *escCmd; /* xcmd escaped to be used in double quotes */ 987 988 run = GNode_ShouldExecute(job->node); 989 990 xcmd = Var_SubstInTarget(ucmd, job->node); 991 /* TODO: handle errors */ 992 xcmdStart = xcmd; 993 994 cmdTemplate = "%s\n"; 995 996 ParseCommandFlags(&xcmd, &cmdFlags); 997 998 /* The '+' command flag overrides the -n or -N options. */ 999 if (cmdFlags.always && !run) { 1000 /* 1001 * We're not actually executing anything... 1002 * but this one needs to be - use compat mode just for it. 1003 */ 1004 (void)Compat_RunCommand(ucmd, job->node, ln); 1005 free(xcmdStart); 1006 return; 1007 } 1008 1009 /* 1010 * If the shell doesn't have error control, the alternate echoing 1011 * will be done (to avoid showing additional error checking code) 1012 * and this needs some characters escaped. 1013 */ 1014 escCmd = shell->hasErrCtl ? NULL : EscapeShellDblQuot(xcmd); 1015 1016 if (!cmdFlags.echo) { 1017 if (job->echo && run && shell->hasEchoCtl) 1018 ShellWriter_EchoOff(wr); 1019 else if (shell->hasErrCtl) 1020 cmdFlags.echo = true; 1021 } 1022 1023 if (cmdFlags.ignerr) { 1024 JobWriteSpecials(job, wr, escCmd, run, &cmdFlags, &cmdTemplate); 1025 } else { 1026 1027 /* 1028 * If errors are being checked and the shell doesn't have 1029 * error control but does supply an runChkTmpl template, then 1030 * set up commands to run through it. 1031 */ 1032 1033 if (!shell->hasErrCtl && shell->runChkTmpl != NULL && 1034 shell->runChkTmpl[0] != '\0') { 1035 if (job->echo && cmdFlags.echo) { 1036 ShellWriter_EchoOff(wr); 1037 ShellWriter_EchoCmd(wr, escCmd); 1038 cmdFlags.echo = false; 1039 } 1040 /* 1041 * If it's a comment line or blank, avoid the possible 1042 * syntax error generated by "{\n} || exit $?". 1043 */ 1044 cmdTemplate = escCmd[0] == shell->commentChar || 1045 escCmd[0] == '\0' 1046 ? shell->runIgnTmpl 1047 : shell->runChkTmpl; 1048 cmdFlags.ignerr = false; 1049 } 1050 } 1051 1052 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0) 1053 ShellWriter_TraceOn(wr); 1054 1055 ShellWriter_WriteFmt(wr, cmdTemplate, xcmd); 1056 free(xcmdStart); 1057 free(escCmd); 1058 1059 if (cmdFlags.ignerr) 1060 ShellWriter_ErrOn(wr, cmdFlags.echo && job->echo); 1061 1062 if (!cmdFlags.echo) 1063 ShellWriter_EchoOn(wr); 1064 } 1065 1066 /* 1067 * Write all commands to the shell file that is later executed. 1068 * 1069 * The special command "..." stops writing and saves the remaining commands 1070 * to be executed later, when the target '.END' is made. 1071 * 1072 * Return whether at least one command was written to the shell file. 1073 */ 1074 static bool 1075 JobWriteCommands(Job *job) 1076 { 1077 StringListNode *ln; 1078 bool seen = false; 1079 ShellWriter wr; 1080 1081 wr.f = job->cmdFILE; 1082 wr.xtraced = false; 1083 1084 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) { 1085 const char *cmd = ln->datum; 1086 1087 if (strcmp(cmd, "...") == 0) { 1088 job->node->type |= OP_SAVE_CMDS; 1089 job->tailCmds = ln->next; 1090 break; 1091 } 1092 1093 JobWriteCommand(job, &wr, ln, ln->datum); 1094 seen = true; 1095 } 1096 1097 return seen; 1098 } 1099 1100 /* 1101 * Save the delayed commands (those after '...'), to be executed later in 1102 * the '.END' node, when everything else is done. 1103 */ 1104 static void 1105 JobSaveCommands(Job *job) 1106 { 1107 StringListNode *ln; 1108 1109 for (ln = job->tailCmds; ln != NULL; ln = ln->next) { 1110 const char *cmd = ln->datum; 1111 char *expanded_cmd; 1112 /* 1113 * XXX: This Var_Subst is only intended to expand the dynamic 1114 * variables such as .TARGET, .IMPSRC. It is not intended to 1115 * expand the other variables as well; see deptgt-end.mk. 1116 */ 1117 expanded_cmd = Var_SubstInTarget(cmd, job->node); 1118 /* TODO: handle errors */ 1119 Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd); 1120 Parse_RegisterCommand(expanded_cmd); 1121 } 1122 } 1123 1124 1125 /* Close both input and output pipes when a job is finished. */ 1126 static void 1127 JobClosePipes(Job *job) 1128 { 1129 clearfd(job); 1130 (void)close(job->outPipe); 1131 job->outPipe = -1; 1132 1133 CollectOutput(job, true); 1134 (void)close(job->inPipe); 1135 job->inPipe = -1; 1136 } 1137 1138 static void 1139 DebugFailedJob(const Job *job) 1140 { 1141 const StringListNode *ln; 1142 1143 if (!DEBUG(ERROR)) 1144 return; 1145 1146 debug_printf("\n"); 1147 debug_printf("*** Failed target: %s\n", job->node->name); 1148 debug_printf("*** In directory: %s\n", curdir); 1149 debug_printf("*** Failed commands:\n"); 1150 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) { 1151 const char *cmd = ln->datum; 1152 debug_printf("\t%s\n", cmd); 1153 1154 if (strchr(cmd, '$') != NULL) { 1155 char *xcmd = Var_Subst(cmd, job->node, VARE_EVAL); 1156 debug_printf("\t=> %s\n", xcmd); 1157 free(xcmd); 1158 } 1159 } 1160 } 1161 1162 static void 1163 JobFinishDoneExitedError(Job *job, int *inout_status) 1164 { 1165 SwitchOutputTo(job->node); 1166 #ifdef USE_META 1167 if (useMeta) { 1168 meta_job_error(job, job->node, 1169 job->ignerr, WEXITSTATUS(*inout_status)); 1170 } 1171 #endif 1172 if (!shouldDieQuietly(job->node, -1)) { 1173 DebugFailedJob(job); 1174 (void)printf("*** [%s] Error code %d%s\n", 1175 job->node->name, WEXITSTATUS(*inout_status), 1176 job->ignerr ? " (ignored)" : ""); 1177 } 1178 1179 if (job->ignerr) 1180 *inout_status = 0; 1181 else { 1182 if (deleteOnError) 1183 JobDeleteTarget(job->node); 1184 PrintOnError(job->node, "\n"); 1185 } 1186 } 1187 1188 static void 1189 JobFinishDoneExited(Job *job, int *inout_status) 1190 { 1191 DEBUG2(JOB, "Target %s, pid %d exited\n", 1192 job->node->name, job->pid); 1193 1194 if (WEXITSTATUS(*inout_status) != 0) 1195 JobFinishDoneExitedError(job, inout_status); 1196 else if (DEBUG(JOB)) { 1197 SwitchOutputTo(job->node); 1198 (void)printf("Target %s, pid %d exited successfully\n", 1199 job->node->name, job->pid); 1200 } 1201 } 1202 1203 static void 1204 JobFinishDoneSignaled(Job *job, int status) 1205 { 1206 SwitchOutputTo(job->node); 1207 DebugFailedJob(job); 1208 (void)printf("*** [%s] Signal %d\n", job->node->name, WTERMSIG(status)); 1209 if (deleteOnError) 1210 JobDeleteTarget(job->node); 1211 } 1212 1213 static void 1214 JobFinishDone(Job *job, int *inout_status) 1215 { 1216 if (WIFEXITED(*inout_status)) 1217 JobFinishDoneExited(job, inout_status); 1218 else 1219 JobFinishDoneSignaled(job, *inout_status); 1220 1221 (void)fflush(stdout); 1222 } 1223 1224 /* 1225 * Finish the job, add deferred commands to the .END node, mark the job as 1226 * free, update parent nodes and start new jobs as available/necessary. 1227 */ 1228 static void 1229 JobFinish(Job *job, int status) 1230 { 1231 bool done, return_job_token; 1232 1233 DEBUG3(JOB, "JobFinish: target %s, pid %d, status %#x\n", 1234 job->node->name, job->pid, status); 1235 1236 if ((WIFEXITED(status) && 1237 ((WEXITSTATUS(status) != 0 && !job->ignerr))) || 1238 WIFSIGNALED(status)) { 1239 /* Finished because of an error. */ 1240 1241 JobClosePipes(job); 1242 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1243 if (fclose(job->cmdFILE) != 0) 1244 Punt("Cannot write shell script for \"%s\": %s", 1245 job->node->name, strerror(errno)); 1246 job->cmdFILE = NULL; 1247 } 1248 done = true; 1249 1250 } else if (WIFEXITED(status)) { 1251 /* 1252 * Deal with ignored errors in -B mode. We need to print a 1253 * message telling of the ignored error as well as to run 1254 * the next command. 1255 */ 1256 done = WEXITSTATUS(status) != 0; 1257 1258 JobClosePipes(job); 1259 1260 } else { 1261 /* No need to close things down or anything. */ 1262 done = false; 1263 } 1264 1265 if (done) 1266 JobFinishDone(job, &status); 1267 1268 #ifdef USE_META 1269 if (useMeta) { 1270 int meta_status = meta_job_finish(job); 1271 if (meta_status != 0 && status == 0) 1272 status = meta_status; 1273 } 1274 #endif 1275 1276 return_job_token = false; 1277 1278 Trace_Log(JOBEND, job); 1279 if (!job->special) { 1280 if (status != 0 || 1281 (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT) 1282 return_job_token = true; 1283 } 1284 1285 if (aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT && 1286 status == 0) { 1287 JobSaveCommands(job); 1288 job->node->made = MADE; 1289 if (!job->special) 1290 return_job_token = true; 1291 Make_Update(job->node); 1292 job->status = JOB_ST_FREE; 1293 } else if (status != 0) { 1294 job_errors++; 1295 job->status = JOB_ST_FREE; 1296 } 1297 1298 if (job_errors > 0 && !opts.keepgoing && aborting != ABORT_INTERRUPT) { 1299 /* Prevent more jobs from getting started. */ 1300 aborting = ABORT_ERROR; 1301 } 1302 1303 if (return_job_token) 1304 TokenPool_Return(); 1305 1306 if (aborting == ABORT_ERROR && jobTokensRunning == 0) { 1307 if (shouldDieQuietly(NULL, -1)) 1308 exit(2); 1309 Fatal("%d error%s", job_errors, job_errors == 1 ? "" : "s"); 1310 } 1311 } 1312 1313 static void 1314 TouchRegular(GNode *gn) 1315 { 1316 const char *file = GNode_Path(gn); 1317 struct utimbuf times; 1318 int fd; 1319 char c; 1320 1321 times.actime = now; 1322 times.modtime = now; 1323 if (utime(file, ×) >= 0) 1324 return; 1325 1326 fd = open(file, O_RDWR | O_CREAT, 0666); 1327 if (fd < 0) { 1328 (void)fprintf(stderr, "*** couldn't touch %s: %s\n", 1329 file, strerror(errno)); 1330 (void)fflush(stderr); 1331 return; /* XXX: What about propagating the error? */ 1332 } 1333 1334 /* 1335 * Last resort: update the file's time stamps in the traditional way. 1336 * XXX: This doesn't work for empty files, which are sometimes used 1337 * as marker files. 1338 */ 1339 if (read(fd, &c, 1) == 1) { 1340 (void)lseek(fd, 0, SEEK_SET); 1341 while (write(fd, &c, 1) == -1 && errno == EAGAIN) 1342 continue; 1343 } 1344 (void)close(fd); /* XXX: What about propagating the error? */ 1345 } 1346 1347 /* 1348 * Touch the given target. Called by Job_Make when the -t flag was given. 1349 * 1350 * The modification date of the file is changed. 1351 * If the file did not exist, it is created. 1352 */ 1353 void 1354 Job_Touch(GNode *gn, bool echo) 1355 { 1356 if (gn->type & 1357 (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC | OP_OPTIONAL | 1358 OP_SPECIAL | OP_PHONY)) { 1359 /* 1360 * These are "virtual" targets and should not really be 1361 * created. 1362 */ 1363 return; 1364 } 1365 1366 if (echo || !GNode_ShouldExecute(gn)) { 1367 (void)fprintf(stdout, "touch %s\n", gn->name); 1368 (void)fflush(stdout); 1369 } 1370 1371 if (!GNode_ShouldExecute(gn)) 1372 return; 1373 1374 if (gn->type & OP_ARCHV) 1375 Arch_Touch(gn); 1376 else if (gn->type & OP_LIB) 1377 Arch_TouchLib(gn); 1378 else 1379 TouchRegular(gn); 1380 } 1381 1382 /* 1383 * Make sure the given node has all the commands it needs. 1384 * 1385 * The node will have commands from the .DEFAULT rule added to it if it 1386 * needs them. 1387 * 1388 * Input: 1389 * gn The target whose commands need verifying 1390 * abortProc Function to abort with message 1391 * 1392 * Results: 1393 * true if the commands are ok. 1394 */ 1395 bool 1396 Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 1397 { 1398 if (GNode_IsTarget(gn)) 1399 return true; 1400 if (!Lst_IsEmpty(&gn->commands)) 1401 return true; 1402 if ((gn->type & OP_LIB) && !Lst_IsEmpty(&gn->children)) 1403 return true; 1404 1405 /* 1406 * No commands. Look for .DEFAULT rule from which we might infer 1407 * commands. 1408 */ 1409 if (defaultNode != NULL && !Lst_IsEmpty(&defaultNode->commands) && 1410 !(gn->type & OP_SPECIAL)) { 1411 /* 1412 * The traditional Make only looks for a .DEFAULT if the node 1413 * was never the target of an operator, so that's what we do 1414 * too. 1415 * 1416 * The .DEFAULT node acts like a transformation rule, in that 1417 * gn also inherits any attributes or sources attached to 1418 * .DEFAULT itself. 1419 */ 1420 Make_HandleUse(defaultNode, gn); 1421 Var_Set(gn, IMPSRC, GNode_VarTarget(gn)); 1422 return true; 1423 } 1424 1425 Dir_UpdateMTime(gn, false); 1426 if (gn->mtime != 0 || (gn->type & OP_SPECIAL)) 1427 return true; 1428 1429 /* 1430 * The node wasn't the target of an operator. We have no .DEFAULT 1431 * rule to go on and the target doesn't already exist. There's 1432 * nothing more we can do for this branch. If the -k flag wasn't 1433 * given, we stop in our tracks, otherwise we just don't update 1434 * this node's parents so they never get examined. 1435 */ 1436 1437 if (gn->flags.fromDepend) { 1438 if (!Job_RunTarget(".STALE", gn->fname)) 1439 fprintf(stdout, 1440 "%s: %s:%u: ignoring stale %s for %s\n", 1441 progname, gn->fname, gn->lineno, makeDependfile, 1442 gn->name); 1443 return true; 1444 } 1445 1446 if (gn->type & OP_OPTIONAL) { 1447 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1448 progname, gn->name, "ignored"); 1449 (void)fflush(stdout); 1450 return true; 1451 } 1452 1453 if (opts.keepgoing) { 1454 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1455 progname, gn->name, "continuing"); 1456 (void)fflush(stdout); 1457 return false; 1458 } 1459 1460 abortProc("don't know how to make %s. Stop", gn->name); 1461 return false; 1462 } 1463 1464 /* 1465 * Execute the shell for the given job. 1466 * 1467 * See Job_CatchOutput for handling the output of the shell. 1468 */ 1469 static void 1470 JobExec(Job *job, char **argv) 1471 { 1472 int cpid; /* ID of new child */ 1473 sigset_t mask; 1474 1475 if (DEBUG(JOB)) { 1476 int i; 1477 1478 debug_printf("Running %s\n", job->node->name); 1479 debug_printf("\tCommand:"); 1480 for (i = 0; argv[i] != NULL; i++) { 1481 debug_printf(" %s", argv[i]); 1482 } 1483 debug_printf("\n"); 1484 } 1485 1486 /* 1487 * Some jobs produce no output, and it's disconcerting to have 1488 * no feedback of their running (since they produce no output, the 1489 * banner with their name in it never appears). This is an attempt to 1490 * provide that feedback, even if nothing follows it. 1491 */ 1492 if (job->echo) 1493 SwitchOutputTo(job->node); 1494 1495 /* No interruptions until this job is in the jobs table. */ 1496 JobsTable_Lock(&mask); 1497 1498 /* Pre-emptively mark job running, pid still zero though */ 1499 job->status = JOB_ST_RUNNING; 1500 1501 Var_ReexportVars(job->node); 1502 Var_ExportStackTrace(job->node->name, NULL); 1503 1504 cpid = FORK_FUNCTION(); 1505 if (cpid == -1) 1506 Punt("fork: %s", strerror(errno)); 1507 1508 if (cpid == 0) { 1509 /* Child */ 1510 sigset_t tmask; 1511 1512 #ifdef USE_META 1513 if (useMeta) 1514 meta_job_child(job); 1515 #endif 1516 /* 1517 * Reset all signal handlers; this is necessary because we 1518 * also need to unblock signals before we exec(2). 1519 */ 1520 JobSigReset(); 1521 1522 sigemptyset(&tmask); 1523 JobsTable_Unlock(&tmask); 1524 1525 if (dup2(fileno(job->cmdFILE), STDIN_FILENO) == -1) 1526 execDie("dup2", "job->cmdFILE"); 1527 if (fcntl(STDIN_FILENO, F_SETFD, 0) == -1) 1528 execDie("clear close-on-exec", "stdin"); 1529 if (lseek(STDIN_FILENO, 0, SEEK_SET) == -1) 1530 execDie("lseek to 0", "stdin"); 1531 1532 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { 1533 /* Pass job token pipe to submakes. */ 1534 if (fcntl(tokenPoolJob.inPipe, F_SETFD, 0) == -1) 1535 execDie("clear close-on-exec", 1536 "tokenPoolJob.inPipe"); 1537 if (fcntl(tokenPoolJob.outPipe, F_SETFD, 0) == -1) 1538 execDie("clear close-on-exec", 1539 "tokenPoolJob.outPipe"); 1540 } 1541 1542 if (dup2(job->outPipe, STDOUT_FILENO) == -1) 1543 execDie("dup2", "job->outPipe"); 1544 1545 /* 1546 * The output channels are marked close on exec. This bit 1547 * was duplicated by dup2 (on some systems), so we have 1548 * to clear it before routing the shell's error output to 1549 * the same place as its standard output. 1550 */ 1551 if (fcntl(STDOUT_FILENO, F_SETFD, 0) == -1) 1552 execDie("clear close-on-exec", "stdout"); 1553 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 1554 execDie("dup2", "1, 2"); 1555 1556 /* 1557 * We want to switch the child into a different process 1558 * family so we can kill it and all its descendants in 1559 * one fell swoop, by killing its process family, but not 1560 * commit suicide. 1561 */ 1562 #if defined(MAKE_NATIVE) || defined(HAVE_SETPGID) 1563 # if defined(SYSV) 1564 /* XXX: dsl - I'm sure this should be setpgrp()... */ 1565 (void)setsid(); 1566 # else 1567 (void)setpgid(0, getpid()); 1568 # endif 1569 #endif 1570 1571 (void)execv(shellPath, argv); 1572 execDie("exec", shellPath); 1573 } 1574 1575 /* Parent, continuing after the child exec */ 1576 job->pid = cpid; 1577 1578 Trace_Log(JOBSTART, job); 1579 1580 #ifdef USE_META 1581 if (useMeta) 1582 meta_job_parent(job, cpid); 1583 #endif 1584 1585 job->outBufLen = 0; 1586 1587 watchfd(job); 1588 1589 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1590 if (fclose(job->cmdFILE) != 0) 1591 Punt("Cannot write shell script for \"%s\": %s", 1592 job->node->name, strerror(errno)); 1593 job->cmdFILE = NULL; 1594 } 1595 1596 if (DEBUG(JOB)) { 1597 debug_printf( 1598 "JobExec: target %s, pid %d added to jobs table\n", 1599 job->node->name, job->pid); 1600 JobTable_Dump("job started"); 1601 } 1602 JobsTable_Unlock(&mask); 1603 } 1604 1605 static void 1606 BuildArgv(Job *job, char **argv) 1607 { 1608 int argc; 1609 static char args[10]; 1610 1611 argv[0] = UNCONST(shellName); 1612 argc = 1; 1613 1614 if ((shell->errFlag != NULL && shell->errFlag[0] != '-') || 1615 (shell->echoFlag != NULL && shell->echoFlag[0] != '-')) { 1616 /* 1617 * At least one of the flags doesn't have a minus before it, 1618 * so merge them together. Have to do this because the Bourne 1619 * shell thinks its second argument is a file to source. 1620 * Grrrr. Note the ten-character limitation on the combined 1621 * arguments. 1622 * 1623 * TODO: Research until when the above comments were 1624 * practically relevant. 1625 */ 1626 (void)snprintf(args, sizeof args, "-%s%s", 1627 !job->ignerr && shell->errFlag != NULL 1628 ? shell->errFlag : "", 1629 job->echo && shell->echoFlag != NULL 1630 ? shell->echoFlag : ""); 1631 if (args[1] != '\0') { 1632 argv[argc] = args; 1633 argc++; 1634 } 1635 } else { 1636 if (!job->ignerr && shell->errFlag != NULL) { 1637 argv[argc] = UNCONST(shell->errFlag); 1638 argc++; 1639 } 1640 if (job->echo && shell->echoFlag != NULL) { 1641 argv[argc] = UNCONST(shell->echoFlag); 1642 argc++; 1643 } 1644 } 1645 argv[argc] = NULL; 1646 } 1647 1648 static void 1649 JobWriteShellCommands(Job *job, GNode *gn, bool *out_run) 1650 { 1651 char fname[MAXPATHLEN]; 1652 int fd; 1653 1654 fd = Job_TempFile(NULL, fname, sizeof fname); 1655 1656 job->cmdFILE = fdopen(fd, "w+"); 1657 if (job->cmdFILE == NULL) 1658 Punt("Could not fdopen %s", fname); 1659 1660 (void)fcntl(fd, F_SETFD, FD_CLOEXEC); 1661 1662 #ifdef USE_META 1663 if (useMeta) { 1664 meta_job_start(job, gn); 1665 if (gn->type & OP_SILENT) /* might have changed */ 1666 job->echo = false; 1667 } 1668 #endif 1669 1670 *out_run = JobWriteCommands(job); 1671 } 1672 1673 void 1674 Job_Make(GNode *gn) 1675 { 1676 Job *job; 1677 char *argv[10]; 1678 bool cmdsOK; /* true if the nodes commands were all right */ 1679 bool run; 1680 1681 for (job = job_table; job < job_table_end; job++) { 1682 if (job->status == JOB_ST_FREE) 1683 break; 1684 } 1685 if (job >= job_table_end) 1686 Punt("Job_Make no job slots vacant"); 1687 1688 memset(job, 0, sizeof *job); 1689 job->node = gn; 1690 job->tailCmds = NULL; 1691 job->status = JOB_ST_SET_UP; 1692 1693 job->special = (gn->type & OP_SPECIAL) != OP_NONE; 1694 job->ignerr = opts.ignoreErrors || gn->type & OP_IGNORE; 1695 job->echo = !(opts.silent || gn->type & OP_SILENT); 1696 1697 /* 1698 * Check the commands now so any attributes from .DEFAULT have a 1699 * chance to migrate to the node. 1700 */ 1701 cmdsOK = Job_CheckCommands(gn, Error); 1702 1703 job->inPollfd = NULL; 1704 1705 if (Lst_IsEmpty(&gn->commands)) { 1706 job->cmdFILE = stdout; 1707 run = false; 1708 1709 if (!cmdsOK) { 1710 PrintOnError(gn, "\n"); 1711 DieHorribly(); 1712 } 1713 } else if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) || 1714 (!opts.noExecute && !opts.touch)) { 1715 int parseErrorsBefore; 1716 1717 if (!cmdsOK) { 1718 PrintOnError(gn, "\n"); 1719 DieHorribly(); 1720 } 1721 1722 parseErrorsBefore = parseErrors; 1723 JobWriteShellCommands(job, gn, &run); 1724 if (parseErrors != parseErrorsBefore) 1725 run = false; 1726 (void)fflush(job->cmdFILE); 1727 } else if (!GNode_ShouldExecute(gn)) { 1728 SwitchOutputTo(gn); 1729 job->cmdFILE = stdout; 1730 if (cmdsOK) 1731 JobWriteCommands(job); 1732 run = false; 1733 (void)fflush(job->cmdFILE); 1734 } else { 1735 Job_Touch(gn, job->echo); 1736 run = false; 1737 } 1738 1739 if (!run) { 1740 if (!job->special) 1741 TokenPool_Return(); 1742 1743 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1744 (void)fclose(job->cmdFILE); 1745 job->cmdFILE = NULL; 1746 } 1747 1748 if (cmdsOK && aborting == ABORT_NONE) { 1749 JobSaveCommands(job); 1750 job->node->made = MADE; 1751 Make_Update(job->node); 1752 } 1753 job->status = JOB_ST_FREE; 1754 return; 1755 } 1756 1757 BuildArgv(job, argv); 1758 JobCreatePipe(job, 3); 1759 JobExec(job, argv); 1760 } 1761 1762 /* 1763 * If the shell has an output filter (which only csh and ksh have by default), 1764 * print the output of the child process, skipping the noPrint text of the 1765 * shell. 1766 * 1767 * Return the part of the output that the calling function needs to output by 1768 * itself. 1769 */ 1770 static const char * 1771 PrintFilteredOutput(Job *job, size_t len) 1772 { 1773 const char *p = job->outBuf, *ep, *endp; 1774 1775 if (shell->noPrint == NULL || shell->noPrint[0] == '\0') 1776 return p; 1777 1778 endp = p + len; 1779 while ((ep = strstr(p, shell->noPrint)) != NULL && ep < endp) { 1780 if (ep > p) { 1781 if (!opts.silent) 1782 SwitchOutputTo(job->node); 1783 (void)fwrite(p, 1, (size_t)(ep - p), stdout); 1784 (void)fflush(stdout); 1785 } 1786 p = ep + shell->noPrintLen; 1787 if (p == endp) 1788 break; 1789 p++; /* skip over the (XXX: assumed) newline */ 1790 cpp_skip_whitespace(&p); 1791 } 1792 return p; 1793 } 1794 1795 /* 1796 * Collect output from the job. Print any complete lines. 1797 * 1798 * In the output of the shell, the 'noPrint' lines are removed. If the 1799 * command is not alone on the line (the character after it is not \0 or 1800 * \n), we do print whatever follows it. 1801 * 1802 * If finish is true, collect all remaining output for the job. 1803 */ 1804 static void 1805 CollectOutput(Job *job, bool finish) 1806 { 1807 const char *p; 1808 size_t nr; /* number of bytes read */ 1809 size_t i; /* auxiliary index into outBuf */ 1810 size_t max; /* limit for i (end of current data) */ 1811 1812 again: 1813 nr = (size_t)read(job->inPipe, job->outBuf + job->outBufLen, 1814 JOB_BUFSIZE - job->outBufLen); 1815 if (nr == (size_t)-1) { 1816 if (errno == EAGAIN) 1817 return; 1818 if (DEBUG(JOB)) 1819 perror("CollectOutput(piperead)"); 1820 nr = 0; 1821 } 1822 1823 if (nr == 0) 1824 finish = false; /* stop looping */ 1825 1826 if (nr == 0 && job->outBufLen > 0) { 1827 job->outBuf[job->outBufLen] = '\n'; 1828 nr = 1; 1829 } 1830 1831 max = job->outBufLen + nr; 1832 job->outBuf[max] = '\0'; 1833 1834 for (i = job->outBufLen; i < max; i++) 1835 if (job->outBuf[i] == '\0') 1836 job->outBuf[i] = ' '; 1837 1838 for (i = max; i > job->outBufLen; i--) 1839 if (job->outBuf[i - 1] == '\n') 1840 break; 1841 1842 if (i == job->outBufLen) { 1843 job->outBufLen = max; 1844 if (max < JOB_BUFSIZE) 1845 goto unfinished_line; 1846 i = max; 1847 } 1848 1849 p = PrintFilteredOutput(job, i); 1850 if (*p != '\0') { 1851 if (!opts.silent) 1852 SwitchOutputTo(job->node); 1853 #ifdef USE_META 1854 if (useMeta) 1855 meta_job_output(job, p, (i < max) ? i : max); 1856 #endif 1857 (void)fwrite(p, 1, (size_t)(job->outBuf + i - p), stdout); 1858 (void)fflush(stdout); 1859 } 1860 memmove(job->outBuf, job->outBuf + i, max - i); 1861 job->outBufLen = max - i; 1862 1863 unfinished_line: 1864 if (finish) 1865 goto again; 1866 } 1867 1868 static void 1869 JobRun(GNode *target) 1870 { 1871 /* Don't let these special jobs overlap with other unrelated jobs. */ 1872 Compat_Make(target, target); 1873 if (GNode_IsError(target)) { 1874 PrintOnError(target, "\n\nStop.\n"); 1875 exit(1); 1876 } 1877 } 1878 1879 void 1880 Job_CatchChildren(void) 1881 { 1882 int pid; 1883 int status; 1884 1885 if (jobTokensRunning == 0) 1886 return; 1887 if (caught_sigchld == 0) 1888 return; 1889 caught_sigchld = 0; 1890 1891 while ((pid = waitpid((pid_t)-1, &status, WNOHANG | WUNTRACED)) > 0) { 1892 DEBUG2(JOB, 1893 "Process with pid %d exited/stopped with status %#x.\n", 1894 pid, status); 1895 JobReapChild(pid, status, true); 1896 } 1897 } 1898 1899 /* 1900 * It is possible that wait[pid]() was called from elsewhere, 1901 * this lets us reap jobs regardless. 1902 */ 1903 void 1904 JobReapChild(pid_t pid, int status, bool isJobs) 1905 { 1906 Job *job; 1907 1908 if (jobTokensRunning == 0) 1909 return; 1910 1911 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); 1912 if (job == NULL) { 1913 if (isJobs && !lurking_children) 1914 Error("Child with pid %d and status %#x not in table?", 1915 pid, status); 1916 return; 1917 } 1918 1919 if (WIFSTOPPED(status)) { 1920 DEBUG2(JOB, "Process for target %s, pid %d stopped\n", 1921 job->node->name, job->pid); 1922 if (!make_suspended) { 1923 switch (WSTOPSIG(status)) { 1924 case SIGTSTP: 1925 (void)printf("*** [%s] Suspended\n", 1926 job->node->name); 1927 break; 1928 case SIGSTOP: 1929 (void)printf("*** [%s] Stopped\n", 1930 job->node->name); 1931 break; 1932 default: 1933 (void)printf("*** [%s] Stopped -- signal %d\n", 1934 job->node->name, WSTOPSIG(status)); 1935 } 1936 job->suspended = true; 1937 } 1938 (void)fflush(stdout); 1939 return; 1940 } 1941 1942 job->status = JOB_ST_FINISHED; 1943 job->exit_status = status; 1944 if (WIFEXITED(status)) 1945 job->node->exit_status = WEXITSTATUS(status); 1946 1947 JobFinish(job, status); 1948 } 1949 1950 static void 1951 Job_Continue(Job *job) 1952 { 1953 DEBUG1(JOB, "Continuing pid %d\n", job->pid); 1954 if (job->suspended) { 1955 (void)printf("*** [%s] Continued\n", job->node->name); 1956 (void)fflush(stdout); 1957 job->suspended = false; 1958 } 1959 if (KILLPG(job->pid, SIGCONT) != 0) 1960 DEBUG1(JOB, "Failed to send SIGCONT to pid %d\n", job->pid); 1961 } 1962 1963 static void 1964 ContinueJobs(void) 1965 { 1966 Job *job; 1967 1968 for (job = job_table; job < job_table_end; job++) { 1969 if (job->status == JOB_ST_RUNNING && 1970 (make_suspended || job->suspended)) 1971 Job_Continue(job); 1972 else if (job->status == JOB_ST_FINISHED) 1973 JobFinish(job, job->exit_status); 1974 } 1975 make_suspended = false; 1976 } 1977 1978 void 1979 Job_CatchOutput(void) 1980 { 1981 int nready; 1982 Job *job; 1983 unsigned i; 1984 1985 (void)fflush(stdout); 1986 1987 do { 1988 /* Maybe skip the job token pipe. */ 1989 nfds_t skip = wantToken ? 0 : 1; 1990 nready = poll(fds + skip, fdsLen - skip, -1); 1991 } while (nready < 0 && errno == EINTR); 1992 1993 if (nready < 0) 1994 Punt("poll: %s", strerror(errno)); 1995 1996 if (nready > 0 && childExitJob.inPollfd->revents & POLLIN) { 1997 char token; 1998 ssize_t count = read(childExitJob.inPipe, &token, 1); 1999 if (count != 1) 2000 Punt("childExitJob.read: %s", 2001 count == 0 ? "EOF" : strerror(errno)); 2002 if (token == CEJ_RESUME_JOBS) 2003 ContinueJobs(); 2004 nready--; 2005 } 2006 2007 Job_CatchChildren(); 2008 if (nready == 0) 2009 return; 2010 2011 for (i = npseudojobs * nfds_per_job(); i < fdsLen; i++) { 2012 if (fds[i].revents == 0) 2013 continue; 2014 job = jobByFdIndex[i]; 2015 if (job->status == JOB_ST_RUNNING) 2016 CollectOutput(job, false); 2017 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2018 /* 2019 * With meta mode, we may have activity on the job's filemon 2020 * descriptor too, which at the moment is any pollfd other 2021 * than job->inPollfd. 2022 */ 2023 if (useMeta && job->inPollfd != &fds[i]) { 2024 if (meta_job_event(job) <= 0) 2025 fds[i].events = 0; /* never mind */ 2026 } 2027 #endif 2028 if (--nready == 0) 2029 return; 2030 } 2031 } 2032 2033 static void 2034 InitShellNameAndPath(void) 2035 { 2036 shellName = shell->name; 2037 2038 #ifdef DEFSHELL_CUSTOM 2039 if (shellName[0] == '/') { 2040 shellPath = bmake_strdup(shellName); 2041 shellName = str_basename(shellPath); 2042 return; 2043 } 2044 #endif 2045 2046 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName); 2047 } 2048 2049 void 2050 Shell_Init(void) 2051 { 2052 if (shellPath == NULL) 2053 InitShellNameAndPath(); 2054 2055 Var_SetWithFlags(SCOPE_CMDLINE, ".SHELL", shellPath, 2056 VAR_SET_INTERNAL|VAR_SET_READONLY); 2057 if (shell->errFlag == NULL) 2058 shell->errFlag = ""; 2059 if (shell->echoFlag == NULL) 2060 shell->echoFlag = ""; 2061 if (shell->hasErrCtl && shell->errFlag[0] != '\0') { 2062 if (shellErrFlag != NULL && 2063 strcmp(shell->errFlag, &shellErrFlag[1]) != 0) { 2064 free(shellErrFlag); 2065 shellErrFlag = NULL; 2066 } 2067 if (shellErrFlag == NULL) 2068 shellErrFlag = str_concat2("-", shell->errFlag); 2069 } else if (shellErrFlag != NULL) { 2070 free(shellErrFlag); 2071 shellErrFlag = NULL; 2072 } 2073 } 2074 2075 /* Return the shell string literal that results in a newline character. */ 2076 const char * 2077 Shell_GetNewline(void) 2078 { 2079 return shell->newline; 2080 } 2081 2082 void 2083 Job_SetPrefix(void) 2084 { 2085 if (targPrefix != NULL) 2086 free(targPrefix); 2087 else if (!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOB.PREFIX")) 2088 Global_Set(".MAKE.JOB.PREFIX", "---"); 2089 2090 targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}", 2091 SCOPE_GLOBAL, VARE_EVAL); 2092 /* TODO: handle errors */ 2093 } 2094 2095 static void 2096 AddSig(int sig, SignalProc handler) 2097 { 2098 if (bmake_signal(sig, SIG_IGN) != SIG_IGN) { 2099 sigaddset(&caught_signals, sig); 2100 (void)bmake_signal(sig, handler); 2101 } 2102 } 2103 2104 void 2105 Job_Init(void) 2106 { 2107 Job_SetPrefix(); 2108 2109 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); 2110 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); 2111 job_table_end = job_table + opts.maxJobs; 2112 wantToken = false; 2113 caught_sigchld = 0; 2114 2115 aborting = ABORT_NONE; 2116 job_errors = 0; 2117 2118 /* 2119 * There is a non-zero chance that we already have children, 2120 * e.g. after 'make -f- <<EOF'. 2121 * Since their termination causes a 'Child (pid) not in table' 2122 * message, Collect the status of any that are already dead, and 2123 * suppress the error message if there are any undead ones. 2124 */ 2125 for (;;) { 2126 int rval, status; 2127 rval = waitpid((pid_t)-1, &status, WNOHANG); 2128 if (rval > 0) 2129 continue; 2130 if (rval == 0) 2131 lurking_children = true; 2132 break; 2133 } 2134 2135 Shell_Init(); 2136 2137 JobCreatePipe(&childExitJob, 3); 2138 2139 { 2140 size_t nfds = (npseudojobs + (size_t)opts.maxJobs) * 2141 nfds_per_job(); 2142 fds = bmake_malloc(sizeof *fds * nfds); 2143 jobByFdIndex = bmake_malloc(sizeof *jobByFdIndex * nfds); 2144 } 2145 2146 /* These are permanent entries and take slots 0 and 1 */ 2147 watchfd(&tokenPoolJob); 2148 watchfd(&childExitJob); 2149 2150 sigemptyset(&caught_signals); 2151 (void)bmake_signal(SIGCHLD, HandleSIGCHLD); 2152 sigaddset(&caught_signals, SIGCHLD); 2153 2154 /* Handle the signals specified by POSIX. */ 2155 AddSig(SIGINT, JobPassSig_int); 2156 AddSig(SIGHUP, JobPassSig_term); 2157 AddSig(SIGTERM, JobPassSig_term); 2158 AddSig(SIGQUIT, JobPassSig_term); 2159 2160 /* 2161 * These signals need to be passed to the jobs, as each job has its 2162 * own process group and thus the terminal driver doesn't forward the 2163 * signals itself. 2164 */ 2165 AddSig(SIGTSTP, JobPassSig_suspend); 2166 AddSig(SIGTTOU, JobPassSig_suspend); 2167 AddSig(SIGTTIN, JobPassSig_suspend); 2168 AddSig(SIGWINCH, JobCondPassSig); 2169 AddSig(SIGCONT, HandleSIGCONT); 2170 2171 (void)Job_RunTarget(".BEGIN", NULL); 2172 /* Create the .END node, see Targ_GetEndNode in Compat_MakeAll. */ 2173 (void)Targ_GetEndNode(); 2174 } 2175 2176 static void 2177 DelSig(int sig) 2178 { 2179 if (sigismember(&caught_signals, sig) != 0) 2180 (void)bmake_signal(sig, SIG_DFL); 2181 } 2182 2183 static void 2184 JobSigReset(void) 2185 { 2186 DelSig(SIGINT); 2187 DelSig(SIGHUP); 2188 DelSig(SIGQUIT); 2189 DelSig(SIGTERM); 2190 DelSig(SIGTSTP); 2191 DelSig(SIGTTOU); 2192 DelSig(SIGTTIN); 2193 DelSig(SIGWINCH); 2194 DelSig(SIGCONT); 2195 (void)bmake_signal(SIGCHLD, SIG_DFL); 2196 } 2197 2198 static Shell * 2199 FindShellByName(const char *name) 2200 { 2201 Shell *sh = shells; 2202 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0]; 2203 2204 for (sh = shells; sh < shellsEnd; sh++) { 2205 if (strcmp(name, sh->name) == 0) 2206 return sh; 2207 } 2208 return NULL; 2209 } 2210 2211 /* 2212 * Parse a shell specification and set up 'shell', shellPath and 2213 * shellName appropriately. 2214 * 2215 * Input: 2216 * line The shell spec 2217 * 2218 * Results: 2219 * Returns false if the specification was incorrect. 2220 * If successful, 'shell' is usable, shellPath is the full path of the 2221 * shell described by 'shell', and shellName is the final component of 2222 * shellPath. 2223 * 2224 * Notes: 2225 * A shell specification has the form ".SHELL: keyword=value...". Double 2226 * quotes can be used to enclose blanks in words. A backslash escapes 2227 * anything (most notably a double-quote and a space) and 2228 * provides the usual escape sequences from C. There should be no 2229 * unnecessary spaces in the word. The keywords are: 2230 * name Name of shell. 2231 * path Location of shell. 2232 * quiet Command to turn off echoing. 2233 * echo Command to turn echoing on 2234 * filter The output from the shell command that turns off 2235 * echoing, to be filtered from the final output. 2236 * echoFlag Flag to turn echoing on at the start. 2237 * errFlag Flag to turn error checking on at the start. 2238 * hasErrCtl True if the shell has error checking control. 2239 * newline String literal to represent a newline character. 2240 * check If hasErrCtl is true: The command to turn on error 2241 * checking. If hasErrCtl is false: The template for a 2242 * shell command that echoes a command for which error 2243 * checking is off. 2244 * ignore If hasErrCtl is true: The command to turn off error 2245 * checking. If hasErrCtl is false: The template for a 2246 * shell command that executes a command so as to ignore 2247 * any errors it returns. 2248 */ 2249 bool 2250 Job_ParseShell(char *line) 2251 { 2252 Words wordsList; 2253 char **words; 2254 char **argv; 2255 size_t argc; 2256 char *path; 2257 Shell newShell; 2258 bool fullSpec = false; 2259 Shell *sh; 2260 2261 /* XXX: don't use line as an iterator variable */ 2262 pp_skip_whitespace(&line); 2263 2264 free(shell_freeIt); 2265 2266 memset(&newShell, 0, sizeof newShell); 2267 2268 wordsList = Str_Words(line, true); 2269 words = wordsList.words; 2270 argc = wordsList.len; 2271 path = wordsList.freeIt; 2272 if (words == NULL) { 2273 Error("Unterminated quoted string [%s]", line); 2274 return false; 2275 } 2276 shell_freeIt = path; 2277 2278 for (path = NULL, argv = words; argc != 0; argc--, argv++) { 2279 char *arg = *argv; 2280 if (strncmp(arg, "path=", 5) == 0) { 2281 path = arg + 5; 2282 } else if (strncmp(arg, "name=", 5) == 0) { 2283 newShell.name = arg + 5; 2284 } else { 2285 if (strncmp(arg, "quiet=", 6) == 0) { 2286 newShell.echoOff = arg + 6; 2287 } else if (strncmp(arg, "echo=", 5) == 0) { 2288 newShell.echoOn = arg + 5; 2289 } else if (strncmp(arg, "filter=", 7) == 0) { 2290 newShell.noPrint = arg + 7; 2291 newShell.noPrintLen = strlen(newShell.noPrint); 2292 } else if (strncmp(arg, "echoFlag=", 9) == 0) { 2293 newShell.echoFlag = arg + 9; 2294 } else if (strncmp(arg, "errFlag=", 8) == 0) { 2295 newShell.errFlag = arg + 8; 2296 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) { 2297 char c = arg[10]; 2298 newShell.hasErrCtl = c == 'Y' || c == 'y' || 2299 c == 'T' || c == 't'; 2300 } else if (strncmp(arg, "newline=", 8) == 0) { 2301 newShell.newline = arg + 8; 2302 } else if (strncmp(arg, "check=", 6) == 0) { 2303 /* 2304 * Before 2020-12-10, these two variables had 2305 * been a single variable. 2306 */ 2307 newShell.errOn = arg + 6; 2308 newShell.echoTmpl = arg + 6; 2309 } else if (strncmp(arg, "ignore=", 7) == 0) { 2310 /* 2311 * Before 2020-12-10, these two variables had 2312 * been a single variable. 2313 */ 2314 newShell.errOff = arg + 7; 2315 newShell.runIgnTmpl = arg + 7; 2316 } else if (strncmp(arg, "errout=", 7) == 0) { 2317 newShell.runChkTmpl = arg + 7; 2318 } else if (strncmp(arg, "comment=", 8) == 0) { 2319 newShell.commentChar = arg[8]; 2320 } else { 2321 Parse_Error(PARSE_FATAL, 2322 "Unknown keyword \"%s\"", arg); 2323 free(words); 2324 return false; 2325 } 2326 fullSpec = true; 2327 } 2328 } 2329 2330 if (path == NULL) { 2331 if (newShell.name == NULL) { 2332 Parse_Error(PARSE_FATAL, 2333 "Neither path nor name specified"); 2334 free(words); 2335 return false; 2336 } else { 2337 if ((sh = FindShellByName(newShell.name)) == NULL) { 2338 Parse_Error(PARSE_WARNING, 2339 "%s: No matching shell", newShell.name); 2340 free(words); 2341 return false; 2342 } 2343 shell = sh; 2344 shellName = newShell.name; 2345 if (shellPath != NULL) { 2346 free(shellPath); 2347 shellPath = NULL; 2348 Shell_Init(); 2349 } 2350 } 2351 } else { 2352 free(shellPath); 2353 shellPath = bmake_strdup(path); 2354 shellName = newShell.name != NULL ? newShell.name 2355 : str_basename(path); 2356 if (!fullSpec) { 2357 if ((sh = FindShellByName(shellName)) == NULL) { 2358 Parse_Error(PARSE_WARNING, 2359 "%s: No matching shell", shellName); 2360 free(words); 2361 return false; 2362 } 2363 shell = sh; 2364 } else { 2365 shell = bmake_malloc(sizeof *shell); 2366 *shell = newShell; 2367 } 2368 /* This will take care of shellErrFlag. */ 2369 Shell_Init(); 2370 } 2371 2372 if (shell->echoOn != NULL && shell->echoOff != NULL) 2373 shell->hasEchoCtl = true; 2374 2375 if (!shell->hasErrCtl) { 2376 if (shell->echoTmpl == NULL) 2377 shell->echoTmpl = ""; 2378 if (shell->runIgnTmpl == NULL) 2379 shell->runIgnTmpl = "%s\n"; 2380 } 2381 2382 /* 2383 * Do not free up the words themselves, since they may be in use 2384 * by the shell specification. 2385 */ 2386 free(words); 2387 return true; 2388 } 2389 2390 /* 2391 * After receiving an interrupt signal, terminate all child processes and if 2392 * necessary make the .INTERRUPT target. 2393 */ 2394 static void 2395 JobInterrupt(bool runINTERRUPT, int signo) 2396 { 2397 Job *job; 2398 sigset_t mask; 2399 2400 aborting = ABORT_INTERRUPT; 2401 2402 JobsTable_Lock(&mask); 2403 2404 for (job = job_table; job < job_table_end; job++) { 2405 if (job->status == JOB_ST_RUNNING && job->pid != 0) { 2406 DEBUG2(JOB, 2407 "JobInterrupt passing signal %d to child %d.\n", 2408 signo, job->pid); 2409 KILLPG(job->pid, signo); 2410 } 2411 } 2412 2413 for (job = job_table; job < job_table_end; job++) { 2414 if (job->status == JOB_ST_RUNNING && job->pid != 0) { 2415 int status; 2416 (void)waitpid(job->pid, &status, 0); 2417 JobDeleteTarget(job->node); 2418 } 2419 } 2420 2421 JobsTable_Unlock(&mask); 2422 2423 if (runINTERRUPT && !opts.touch) { 2424 GNode *dotInterrupt = Targ_FindNode(".INTERRUPT"); 2425 if (dotInterrupt != NULL) { 2426 opts.ignoreErrors = false; 2427 JobRun(dotInterrupt); 2428 } 2429 } 2430 Trace_Log(MAKEINTR, NULL); 2431 exit(signo); /* XXX: why signo? */ 2432 } 2433 2434 /* Make the .END target, returning the number of job-related errors. */ 2435 int 2436 Job_MakeDotEnd(void) 2437 { 2438 GNode *dotEnd = Targ_GetEndNode(); 2439 if (!Lst_IsEmpty(&dotEnd->commands) || 2440 !Lst_IsEmpty(&dotEnd->children)) { 2441 if (job_errors != 0) 2442 Error("Errors reported so .END ignored"); 2443 else 2444 JobRun(dotEnd); 2445 } 2446 return job_errors; 2447 } 2448 2449 #ifdef CLEANUP 2450 void 2451 Job_End(void) 2452 { 2453 free(shell_freeIt); 2454 } 2455 #endif 2456 2457 /* Waits for all running jobs to finish. */ 2458 void 2459 Job_Wait(void) 2460 { 2461 aborting = ABORT_WAIT; /* Prevent other jobs from starting. */ 2462 while (jobTokensRunning != 0) 2463 Job_CatchOutput(); 2464 aborting = ABORT_NONE; 2465 } 2466 2467 /* 2468 * Abort all currently running jobs without handling output or anything. 2469 * This function is to be called only in the event of a major error. 2470 * Most definitely NOT to be called from JobInterrupt. 2471 */ 2472 void 2473 Job_AbortAll(void) 2474 { 2475 Job *job; 2476 int status; 2477 2478 aborting = ABORT_ERROR; 2479 2480 if (jobTokensRunning != 0) { 2481 for (job = job_table; job < job_table_end; job++) { 2482 if (job->status != JOB_ST_RUNNING) 2483 continue; 2484 KILLPG(job->pid, SIGINT); 2485 KILLPG(job->pid, SIGKILL); 2486 } 2487 } 2488 2489 while (waitpid((pid_t)-1, &status, WNOHANG) > 0) 2490 continue; 2491 } 2492 2493 static void 2494 watchfd(Job *job) 2495 { 2496 if (job->inPollfd != NULL) 2497 Punt("Watching watched job"); 2498 2499 fds[fdsLen].fd = job->inPipe; 2500 fds[fdsLen].events = POLLIN; 2501 jobByFdIndex[fdsLen] = job; 2502 job->inPollfd = &fds[fdsLen]; 2503 fdsLen++; 2504 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2505 if (useMeta) { 2506 fds[fdsLen].fd = meta_job_fd(job); 2507 fds[fdsLen].events = fds[fdsLen].fd == -1 ? 0 : POLLIN; 2508 jobByFdIndex[fdsLen] = job; 2509 fdsLen++; 2510 } 2511 #endif 2512 } 2513 2514 static void 2515 clearfd(Job *job) 2516 { 2517 size_t i; 2518 if (job->inPollfd == NULL) 2519 Punt("Unwatching unwatched job"); 2520 i = (size_t)(job->inPollfd - fds); 2521 fdsLen--; 2522 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2523 if (useMeta) { 2524 assert(nfds_per_job() == 2); 2525 if (i % 2 != 0) 2526 Punt("odd-numbered fd with meta"); 2527 fdsLen--; 2528 } 2529 #endif 2530 /* Move last job in table into hole made by dead job. */ 2531 if (fdsLen != i) { 2532 fds[i] = fds[fdsLen]; 2533 jobByFdIndex[i] = jobByFdIndex[fdsLen]; 2534 jobByFdIndex[i]->inPollfd = &fds[i]; 2535 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2536 if (useMeta) { 2537 fds[i + 1] = fds[fdsLen + 1]; 2538 jobByFdIndex[i + 1] = jobByFdIndex[fdsLen + 1]; 2539 } 2540 #endif 2541 } 2542 job->inPollfd = NULL; 2543 } 2544 2545 int 2546 Job_TempFile(const char *pattern, char *tfile, size_t tfile_sz) 2547 { 2548 int fd; 2549 sigset_t mask; 2550 2551 JobsTable_Lock(&mask); 2552 fd = mkTempFile(pattern, tfile, tfile_sz); 2553 if (tfile != NULL && !DEBUG(SCRIPT)) 2554 unlink(tfile); 2555 JobsTable_Unlock(&mask); 2556 2557 return fd; 2558 } 2559 2560 static void 2561 TokenPool_Write(char tok) 2562 { 2563 if (write(tokenPoolJob.outPipe, &tok, 1) != 1) 2564 Punt("Cannot write \"%c\" to the token pool: %s", 2565 tok, strerror(errno)); 2566 } 2567 2568 /* 2569 * Put a token (back) into the job token pool. 2570 * This allows a make process to start a build job. 2571 */ 2572 static void 2573 TokenPool_Add(void) 2574 { 2575 char tok = JOB_TOKENS[aborting], tok1; 2576 2577 /* If we are depositing an error token, flush everything else. */ 2578 while (tok != '+' && read(tokenPoolJob.inPipe, &tok1, 1) == 1) 2579 continue; 2580 2581 DEBUG3(JOB, "TokenPool_Add: pid %d, aborting %s, token %c\n", 2582 getpid(), aborting_name[aborting], tok); 2583 TokenPool_Write(tok); 2584 } 2585 2586 static void 2587 TokenPool_InitClient(int tokenPoolReader, int tokenPoolWriter) 2588 { 2589 tokenPoolJob.inPipe = tokenPoolReader; 2590 tokenPoolJob.outPipe = tokenPoolWriter; 2591 (void)fcntl(tokenPoolReader, F_SETFD, FD_CLOEXEC); 2592 (void)fcntl(tokenPoolWriter, F_SETFD, FD_CLOEXEC); 2593 } 2594 2595 /* Prepare the job token pipe in the root make process. */ 2596 static void 2597 TokenPool_InitServer(int maxJobTokens) 2598 { 2599 int i; 2600 char jobarg[64]; 2601 2602 JobCreatePipe(&tokenPoolJob, 15); 2603 2604 snprintf(jobarg, sizeof jobarg, "%d,%d", 2605 tokenPoolJob.inPipe, tokenPoolJob.outPipe); 2606 2607 Global_Append(MAKEFLAGS, "-J"); 2608 Global_Append(MAKEFLAGS, jobarg); 2609 2610 /* 2611 * Preload the job pipe with one token per job, save the one 2612 * "extra" token for the primary job. 2613 */ 2614 SetNonblocking(tokenPoolJob.outPipe); 2615 for (i = 1; i < maxJobTokens; i++) 2616 TokenPool_Add(); 2617 } 2618 2619 void 2620 TokenPool_Init(int maxJobTokens, int tokenPoolReader, int tokenPoolWriter) 2621 { 2622 if (tokenPoolReader >= 0 && tokenPoolWriter >= 0) 2623 TokenPool_InitClient(tokenPoolReader, tokenPoolWriter); 2624 else 2625 TokenPool_InitServer(maxJobTokens); 2626 } 2627 2628 /* Return a taken token to the pool. */ 2629 void 2630 TokenPool_Return(void) 2631 { 2632 jobTokensRunning--; 2633 if (jobTokensRunning < 0) 2634 Punt("token botch"); 2635 if (jobTokensRunning != 0 || JOB_TOKENS[aborting] != '+') 2636 TokenPool_Add(); 2637 } 2638 2639 /* 2640 * Attempt to take a token from the pool. 2641 * 2642 * If the pool is empty, set wantToken so that we wake up when a token is 2643 * released. 2644 * 2645 * Returns true if a token was taken, and false if the pool is currently 2646 * empty. 2647 */ 2648 bool 2649 TokenPool_Take(void) 2650 { 2651 char tok, tok1; 2652 ssize_t count; 2653 2654 wantToken = false; 2655 DEBUG3(JOB, "TokenPool_Take: pid %d, aborting %s, running %d\n", 2656 getpid(), aborting_name[aborting], jobTokensRunning); 2657 2658 if (aborting != ABORT_NONE || jobTokensRunning >= opts.maxJobs) 2659 return false; 2660 2661 count = read(tokenPoolJob.inPipe, &tok, 1); 2662 if (count == 0) 2663 Fatal("eof on job pipe"); 2664 if (count < 0 && jobTokensRunning != 0) { 2665 if (errno != EAGAIN) 2666 Fatal("job pipe read: %s", strerror(errno)); 2667 DEBUG1(JOB, "TokenPool_Take: pid %d blocked for token\n", 2668 getpid()); 2669 wantToken = true; 2670 return false; 2671 } 2672 2673 if (count == 1 && tok != '+') { 2674 /* make being aborted - remove any other job tokens */ 2675 DEBUG2(JOB, "TokenPool_Take: pid %d aborted by token %c\n", 2676 getpid(), tok); 2677 while (read(tokenPoolJob.inPipe, &tok1, 1) == 1) 2678 continue; 2679 /* And put the stopper back */ 2680 TokenPool_Write(tok); 2681 if (shouldDieQuietly(NULL, 1)) { 2682 Job_Wait(); 2683 exit(6); 2684 } 2685 Fatal("A failure has been detected " 2686 "in another branch of the parallel make"); 2687 } 2688 2689 if (count == 1 && jobTokensRunning == 0) 2690 /* We didn't want the token really */ 2691 TokenPool_Write(tok); 2692 2693 jobTokensRunning++; 2694 DEBUG1(JOB, "TokenPool_Take: pid %d took a token\n", getpid()); 2695 return true; 2696 } 2697 2698 /* Make the named target if found, exit if the target fails. */ 2699 bool 2700 Job_RunTarget(const char *target, const char *fname) 2701 { 2702 GNode *gn = Targ_FindNode(target); 2703 if (gn == NULL) 2704 return false; 2705 2706 if (fname != NULL) 2707 Var_Set(gn, ALLSRC, fname); 2708 2709 JobRun(gn); 2710 return true; 2711 } 2712 2713 #ifdef USE_SELECT 2714 int 2715 emul_poll(struct pollfd *fd, int nfd, int timeout) 2716 { 2717 fd_set rfds, wfds; 2718 int i, maxfd, nselect, npoll; 2719 struct timeval tv, *tvp; 2720 long usecs; 2721 2722 FD_ZERO(&rfds); 2723 FD_ZERO(&wfds); 2724 2725 maxfd = -1; 2726 for (i = 0; i < nfd; i++) { 2727 fd[i].revents = 0; 2728 2729 if (fd[i].events & POLLIN) 2730 FD_SET(fd[i].fd, &rfds); 2731 2732 if (fd[i].events & POLLOUT) 2733 FD_SET(fd[i].fd, &wfds); 2734 2735 if (fd[i].fd > maxfd) 2736 maxfd = fd[i].fd; 2737 } 2738 2739 if (maxfd >= FD_SETSIZE) { 2740 Punt("Ran out of fd_set slots; " 2741 "recompile with a larger FD_SETSIZE."); 2742 } 2743 2744 if (timeout < 0) { 2745 tvp = NULL; 2746 } else { 2747 usecs = timeout * 1000; 2748 tv.tv_sec = usecs / 1000000; 2749 tv.tv_usec = usecs % 1000000; 2750 tvp = &tv; 2751 } 2752 2753 nselect = select(maxfd + 1, &rfds, &wfds, NULL, tvp); 2754 2755 if (nselect <= 0) 2756 return nselect; 2757 2758 npoll = 0; 2759 for (i = 0; i < nfd; i++) { 2760 if (FD_ISSET(fd[i].fd, &rfds)) 2761 fd[i].revents |= POLLIN; 2762 2763 if (FD_ISSET(fd[i].fd, &wfds)) 2764 fd[i].revents |= POLLOUT; 2765 2766 if (fd[i].revents) 2767 npoll++; 2768 } 2769 2770 return npoll; 2771 } 2772 #endif /* USE_SELECT */ 2773