Deleted Added
sdiff udiff text old ( 138232 ) new ( 138264 )
full compact
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1988, 1989 by Adam de Boor
5 * Copyright (c) 1989 by Berkeley Softworks
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by

--- 26 unchanged lines hidden (view full) ---

35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 * @(#)job.c 8.2 (Berkeley) 3/19/94
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.bin/make/job.c 138264 2004-12-01 10:29:20Z harti $");
44
45#ifndef OLD_JOKE
46#define OLD_JOKE 0
47#endif /* OLD_JOKE */
48
49/*-
50 * job.c --
51 * handle the creation etc. of our child processes.

--- 271 unchanged lines hidden (view full) ---

323 * Side Effects:
324 * None, except the job may bite it.
325 *
326 *-----------------------------------------------------------------------
327 */
328static int
329JobCondPassSig(void *jobp, void *signop)
330{
331 Job *job = jobp;
332 int signo = *(int *)signop;
333
334 DEBUGF(JOB, ("JobCondPassSig passing signal %d to child %d.\n",
335 signo, job->pid));
336 KILL(job->pid, signo);
337 return (0);
338}
339

--- 17 unchanged lines hidden (view full) ---

357 sigset_t nmask, omask;
358 struct sigaction act;
359
360 sigemptyset(&nmask);
361 sigaddset(&nmask, signo);
362 sigprocmask(SIG_SETMASK, &nmask, &omask);
363
364 DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo));
365 Lst_ForEach(jobs, JobCondPassSig, &signo);
366
367 /*
368 * Deal with proper cleanup based on the signal received. We only run
369 * the .INTERRUPT target if the signal was in fact an interrupt. The other
370 * three termination signals are more of a "get out *now*" command.
371 */
372 if (signo == SIGINT) {
373 JobInterrupt(TRUE, signo);

--- 22 unchanged lines hidden (view full) ---

396
397 DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n",
398 ~0 & ~(1 << (signo - 1))));
399 signal(signo, SIG_DFL);
400
401 KILL(getpid(), signo);
402
403 signo = SIGCONT;
404 Lst_ForEach(jobs, JobCondPassSig, &signo);
405
406 sigprocmask(SIG_SETMASK, &omask, NULL);
407 sigprocmask(SIG_SETMASK, &omask, NULL);
408 act.sa_handler = JobPassSig;
409 sigaction(signo, &act, NULL);
410}
411
412/*-

--- 8 unchanged lines hidden (view full) ---

421 *
422 * Side Effects:
423 * None
424 *-----------------------------------------------------------------------
425 */
426static int
427JobCmpPid(void *job, void *pid)
428{
429
430 return (*(int *)pid - ((Job *)job)->pid);
431}
432
433/*-
434 *-----------------------------------------------------------------------
435 * JobPrintCommand --
436 * Put out another command for the given job. If the command starts
437 * with an @ or a - we process it specially. In the former case,

--- 29 unchanged lines hidden (view full) ---

467 * into the command file */
468 Boolean errOff = FALSE; /* true if we turned error checking
469 * off before printing the command
470 * and need to turn it back on */
471 char *cmdTemplate; /* Template to use when printing the
472 * command */
473 char *cmdStart; /* Start of expanded command */
474 LstNode cmdNode; /* Node for replacing the command */
475 char *cmd = cmdp;
476 Job *job = jobp;
477
478 noSpecials = (noExecute && !(job->node->type & OP_MAKE));
479
480 if (strcmp(cmd, "...") == 0) {
481 job->node->type |= OP_SAVE_CMDS;
482 if ((job->flags & JOB_IGNDOTS) == 0) {
483 job->tailCmds = Lst_Succ(Lst_Member(job->node->commands, cmd));
484 return (1);
485 }
486 return (0);
487 }
488
489#define DBPRINTF(fmt, arg) \
490 DEBUGF(JOB, (fmt, arg)); \
491 fprintf(job->cmdFILE, fmt, arg); \
492 fflush(job->cmdFILE);
493
494 numCommands += 1;
495
496 /*
497 * For debugging, we replace each command with the result of expanding
498 * the variables in the command.
499 */
500 cmdNode = Lst_Member(job->node->commands, cmd);
501 cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE);
502 Lst_Replace(cmdNode, cmdStart);
503
504 cmdTemplate = "%s\n";
505
506 /*
507 * Check for leading @', -' or +'s to control echoing, error checking,
508 * and execution on -n.
509 */
510 while (*cmd == '@' || *cmd == '-' || *cmd == '+') {

--- 88 unchanged lines hidden (view full) ---

599 DBPRINTF(cmdTemplate, cmd);
600
601 if (errOff) {
602 /*
603 * If echoing is already off, there's no point in issuing the
604 * echoOff command. Otherwise we issue it and pretend it was on
605 * for the whole command...
606 */
607 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl) {
608 DBPRINTF("%s\n", commandShell->echoOff);
609 shutUp = TRUE;
610 }
611 DBPRINTF("%s\n", commandShell->errCheck);
612 }
613 if (shutUp) {
614 DBPRINTF("%s\n", commandShell->echoOn);
615 }

--- 13 unchanged lines hidden (view full) ---

629 * The command is tacked onto the end of postCommands's commands list.
630 *
631 *-----------------------------------------------------------------------
632 */
633static int
634JobSaveCommand(void *cmd, void *gn)
635{
636
637 cmd = Var_Subst(NULL, cmd, gn, FALSE);
638 Lst_AtEnd(postCommands->commands, cmd);
639 return (0);
640}
641
642
643/*-
644 *-----------------------------------------------------------------------
645 * JobClose --

--- 140 unchanged lines hidden (view full) ---

786 DEBUGF(JOB, ("Process %d stopped.\n", job->pid));
787 if (usePipes && job->node != lastNode) {
788 MESSAGE(out, job->node);
789 lastNode = job->node;
790 }
791 fprintf(out, "*** Stopped -- signal %d\n",
792 WSTOPSIG(*status));
793 job->flags |= JOB_RESUME;
794 Lst_AtEnd(stoppedJobs, job);
795 fflush(out);
796 return;
797 } else if (WTERMSIG(*status) == SIGCONT) {
798 /*
799 * If the beastie has continued, shift the Job from the stopped
800 * list to the running one (or re-stop it if concurrency is
801 * exceeded) and go and get another child.
802 */

--- 12 unchanged lines hidden (view full) ---

815 * because it continued, especially not without killing the
816 * continuing process! That's why this is ifdef'ed out.
817 * FD - 9/17/90
818 */
819 JobRestart(job);
820#endif
821 }
822 job->flags &= ~JOB_CONTINUING;
823 Lst_AtEnd(jobs, job);
824 nJobs += 1;
825 DEBUGF(JOB, ("Process %d is continuing locally.\n", job->pid));
826 if (nJobs == maxJobs) {
827 jobFull = TRUE;
828 DEBUGF(JOB, ("Job queue is full.\n"));
829 }
830 fflush(out);
831 return;

--- 49 unchanged lines hidden (view full) ---

881 /*
882 * As long as we aren't aborting and the job didn't return a non-zero
883 * status that we shouldn't ignore, we call Make_Update to update
884 * the parents. In addition, any saved commands for the node are placed
885 * on the .END target.
886 */
887 if (job->tailCmds != NULL) {
888 Lst_ForEachFrom(job->node->commands, job->tailCmds,
889 JobSaveCommand, job->node);
890 }
891 job->node->made = MADE;
892 Make_Update(job->node);
893 free(job);
894 } else if (*status != 0) {
895 errors += 1;
896 free(job);
897 }

--- 34 unchanged lines hidden (view full) ---

932 *-----------------------------------------------------------------------
933 */
934void
935Job_Touch(GNode *gn, Boolean silent)
936{
937 int streamID; /* ID of stream opened to do the touch */
938 struct utimbuf times; /* Times for utime() call */
939
940 if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) {
941 /*
942 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
943 * and, as such, shouldn't really be created.
944 */
945 return;
946 }
947
948 if (!silent) {

--- 242 unchanged lines hidden (view full) ---

1191 job->cmdFILE = NULL;
1192 }
1193 }
1194
1195 /*
1196 * Now the job is actually running, add it to the table.
1197 */
1198 nJobs += 1;
1199 Lst_AtEnd(jobs, job);
1200 if (nJobs == maxJobs) {
1201 jobFull = TRUE;
1202 }
1203}
1204
1205/*-
1206 *-----------------------------------------------------------------------
1207 * JobMakeArgv --

--- 174 unchanged lines hidden (view full) ---

1382 if (interrupted) {
1383 JobPassSig(interrupted);
1384 return (JOB_ERROR);
1385 }
1386 if (previous != NULL) {
1387 previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT);
1388 job = previous;
1389 } else {
1390 job = emalloc(sizeof(Job));
1391 flags |= JOB_FIRST;
1392 }
1393
1394 job->node = gn;
1395 job->tailCmds = NULL;
1396
1397 /*
1398 * Set the initial value of the flags for this job based on the global

--- 64 unchanged lines hidden (view full) ---

1463 * ellipsis, note that there's nothing more to execute.
1464 */
1465 if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){
1466 cmdsOK = FALSE;
1467 } else {
1468 LstNode ln = Lst_Next(gn->commands);
1469
1470 if ((ln == NULL) ||
1471 JobPrintCommand(Lst_Datum(ln), job))
1472 {
1473 noExec = TRUE;
1474 Lst_Close(gn->commands);
1475 }
1476 if (noExec && !(job->flags & JOB_FIRST)) {
1477 /*
1478 * If we're not going to execute anything, the job
1479 * is done and we need to close down the various

--- 8 unchanged lines hidden (view full) ---

1488 JobClose(job);
1489 }
1490 }
1491 } else {
1492 /*
1493 * We can do all the commands at once. hooray for sanity
1494 */
1495 numCommands = 0;
1496 Lst_ForEach(gn->commands, JobPrintCommand, job);
1497
1498 /*
1499 * If we didn't print out any commands to the shell script,
1500 * there's not much point in executing the shell, is there?
1501 */
1502 if (numCommands == 0) {
1503 noExec = TRUE;
1504 }

--- 9 unchanged lines hidden (view full) ---

1514 }
1515 job->cmdFILE = stdout;
1516 /*
1517 * Only print the commands if they're ok, but don't die if they're
1518 * not -- just let the user know they're bad and keep going. It
1519 * doesn't do any harm in this case and may do some good.
1520 */
1521 if (cmdsOK) {
1522 Lst_ForEach(gn->commands, JobPrintCommand, job);
1523 }
1524 /*
1525 * Don't execute the shell, thank you.
1526 */
1527 noExec = TRUE;
1528 } else {
1529 /*
1530 * Just touch the target and note that no shell should be executed.
1531 * Set cmdFILE to stdout to make life easier. Check the commands, too,
1532 * but don't die if they're no good -- it does no harm to keep working
1533 * up the graph.
1534 */
1535 job->cmdFILE = stdout;
1536 Job_Touch(gn, job->flags & JOB_SILENT);
1537 noExec = TRUE;
1538 }
1539
1540 /*
1541 * If we're not supposed to execute a shell, don't.
1542 */
1543 if (noExec) {
1544 /*

--- 9 unchanged lines hidden (view full) ---

1554 /*
1555 * We only want to work our way up the graph if we aren't here because
1556 * the commands for the job were no good.
1557 */
1558 if (cmdsOK) {
1559 if (aborting == 0) {
1560 if (job->tailCmds != NULL) {
1561 Lst_ForEachFrom(job->node->commands, job->tailCmds,
1562 JobSaveCommand, job->node);
1563 }
1564 job->node->made = MADE;
1565 Make_Update(job->node);
1566 }
1567 free(job);
1568 return(JOB_FINISHED);
1569 } else {
1570 free(job);

--- 40 unchanged lines hidden (view full) ---

1611 * some other job finishes. Note that the special jobs (.BEGIN,
1612 * .INTERRUPT and .END) may be run even when the limit has been reached
1613 * (e.g. when maxJobs == 0).
1614 */
1615 jobFull = TRUE;
1616
1617 DEBUGF(JOB, ("Can only run job locally.\n"));
1618 job->flags |= JOB_RESTART;
1619 Lst_AtEnd(stoppedJobs, job);
1620 } else {
1621 if (nJobs >= maxJobs) {
1622 /*
1623 * If we're running this job locally as a special case (see above),
1624 * at least say the table is full.
1625 */
1626 jobFull = TRUE;
1627 DEBUGF(JOB, ("Local job queue is full.\n"));

--- 81 unchanged lines hidden (view full) ---

1709 int nr; /* number of bytes read */
1710 int i; /* auxiliary index into outBuf */
1711 int max; /* limit for i (end of current data) */
1712 int nRead; /* (Temporary) number of bytes read */
1713
1714 FILE *oFILE; /* Stream pointer to shell's output file */
1715 char inLine[132];
1716
1717 if (usePipes) {
1718 /*
1719 * Read as many bytes as will fit in the buffer.
1720 */
1721end_loop:
1722 gotNL = FALSE;
1723 fbuf = FALSE;
1724

--- 120 unchanged lines hidden (view full) ---

1845 * to print the noPrint line for the shell we used, then close and
1846 * remove the temporary file. Very simple.
1847 *
1848 * Change to read in blocks and do FindSubString type things as for
1849 * pipes? That would allow for "@echo -n..."
1850 */
1851 oFILE = fopen(job->outFile, "r");
1852 if (oFILE != NULL) {
1853 fprintf(stdout, "Results of making %s:\n", job->node->name);
1854 fflush(stdout);
1855 while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {
1856 char *cp, *endp, *oendp;
1857
1858 cp = inLine;
1859 oendp = endp = inLine + strlen(inLine);
1860 if (endp[-1] == '\n') {
1861 *--endp = '\0';
1862 }

--- 6 unchanged lines hidden (view full) ---

1869 */
1870 fprintf(stdout, "%s", cp);
1871 fflush(stdout);
1872 if (endp != oendp) {
1873 fprintf(stdout, "\n");
1874 fflush(stdout);
1875 }
1876 }
1877 fclose(oFILE);
1878 eunlink(job->outFile);
1879 }
1880 }
1881}
1882
1883/*-
1884 *-----------------------------------------------------------------------
1885 * Job_CatchChildren --
1886 * Handle the exit of a child. Called from Make_Make.

--- 28 unchanged lines hidden (view full) ---

1915 }
1916
1917 for (;;) {
1918 pid = waitpid((pid_t)-1, &status, (block ? 0 : WNOHANG) | WUNTRACED);
1919 if (pid <= 0)
1920 break;
1921 DEBUGF(JOB, ("Process %d exited or stopped.\n", pid));
1922
1923 jnode = Lst_Find(jobs, &pid, JobCmpPid);
1924
1925 if (jnode == NULL) {
1926 if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) {
1927 jnode = Lst_Find(stoppedJobs, &pid, JobCmpPid);
1928 if (jnode == NULL) {
1929 Error("Resumed child (%d) not in table", pid);
1930 continue;
1931 }
1932 job = Lst_Datum(jnode);
1933 Lst_Remove(stoppedJobs, jnode);
1934 } else {
1935 Error("Child (%d) not in table?", pid);
1936 continue;
1937 }
1938 } else {
1939 job = Lst_Datum(jnode);
1940 Lst_Remove(jobs, jnode);
1941 nJobs -= 1;
1942 if (fifoFd >= 0 && maxJobs > 1) {
1943 write(fifoFd, "+", 1);
1944 maxJobs--;
1945 if (nJobs >= maxJobs)
1946 jobFull = TRUE;
1947 else

--- 69 unchanged lines hidden (view full) ---

2017 }
2018#else
2019 readfds = outputs;
2020 timeout.tv_sec = SEL_SEC;
2021 timeout.tv_usec = SEL_USEC;
2022 if (flag && jobFull && fifoFd >= 0)
2023 FD_SET(fifoFd, &readfds);
2024
2025 nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL,
2026 (fd_set *)NULL, &timeout);
2027 if (nfds <= 0) {
2028 if (interrupted)
2029 JobPassSig(interrupted);
2030 return;
2031 }
2032 if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) {
2033 if (--nfds <= 0)
2034 return;
2035 }
2036 if (Lst_Open(jobs) == FAILURE) {
2037 Punt("Cannot open job table");
2038 }
2039 while (nfds && (ln = Lst_Next(jobs)) != NULL) {
2040 job = Lst_Datum(ln);
2041 if (FD_ISSET(job->inPipe, &readfds)) {
2042 JobDoOutput(job, FALSE);
2043 nfds -= 1;
2044 }
2045 }
2046 Lst_Close(jobs);
2047#endif /* !USE_KQUEUE */
2048 }

--- 153 unchanged lines hidden (view full) ---

2202 if (fifoFd >= 0) {
2203 fifoMaster = 1;
2204 fcntl(fifoFd, F_SETFL, O_NONBLOCK);
2205 env = fifoName;
2206 setenv("MAKE_JOBS_FIFO", env, 1);
2207 while (maxproc-- > 0) {
2208 write(fifoFd, "+", 1);
2209 }
2210 /* The master make does not get a magic token */
2211 jobFull = TRUE;
2212 maxJobs = 0;
2213 } else {
2214 unlink(fifoName);
2215 env = NULL;
2216 }
2217 }
2218 } else if (env != NULL) {

--- 82 unchanged lines hidden (view full) ---

2301 if ((kqfd = kqueue()) == -1) {
2302 Punt("kqueue: %s", strerror(errno));
2303 }
2304#endif
2305
2306 begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);
2307
2308 if (begin != NULL) {
2309 JobStart(begin, JOB_SPECIAL, (Job *)NULL);
2310 while (nJobs) {
2311 Job_CatchOutput(0);
2312 Job_CatchChildren(!usePipes);
2313 }
2314 }
2315 postCommands = Targ_FindNode(".END", TARG_CREATE);
2316}
2317

--- 316 unchanged lines hidden (view full) ---

2634 LstNode ln; /* element in job table */
2635 Job *job = NULL; /* job descriptor in that element */
2636 GNode *interrupt; /* the node describing the .INTERRUPT target */
2637
2638 aborting = ABORT_INTERRUPT;
2639
2640 Lst_Open(jobs);
2641 while ((ln = Lst_Next(jobs)) != NULL) {
2642 job = Lst_Datum(ln);
2643
2644 if (!Targ_Precious(job->node)) {
2645 char *file = (job->node->path == NULL ?
2646 job->node->name :
2647 job->node->path);
2648 if (!noExecute && eunlink(file) != -1) {
2649 Error("*** %s removed", file);
2650 }

--- 9 unchanged lines hidden (view full) ---

2660 /* clear the interrupted flag because we would get an
2661 * infinite loop otherwise */
2662 interrupted = 0;
2663
2664 interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
2665 if (interrupt != NULL) {
2666 ignoreErrors = FALSE;
2667
2668 JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL);
2669 while (nJobs) {
2670 Job_CatchOutput(0);
2671 Job_CatchChildren(!usePipes);
2672 }
2673 }
2674 }
2675}
2676

--- 77 unchanged lines hidden (view full) ---

2754{
2755 LstNode ln; /* element in job table */
2756 Job *job; /* the job descriptor in that element */
2757 int foo;
2758
2759 aborting = ABORT_ERROR;
2760
2761 if (nJobs) {
2762 Lst_Open(jobs);
2763 while ((ln = Lst_Next(jobs)) != NULL) {
2764 job = Lst_Datum(ln);
2765
2766 /*
2767 * kill the child process with increasingly drastic signals to make
2768 * darn sure it's dead.
2769 */
2770 KILL(job->pid, SIGINT);
2771 KILL(job->pid, SIGKILL);
2772 }

--- 21 unchanged lines hidden (view full) ---

2794 *
2795 *-----------------------------------------------------------------------
2796 */
2797static void
2798JobRestartJobs(void)
2799{
2800 while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {
2801 DEBUGF(JOB, ("Job queue is not full. Restarting a stopped job.\n"));
2802 JobRestart(Lst_DeQueue(stoppedJobs));
2803 }
2804}