Annotation of src/usr.bin/make/job.c, Revision 1.105
1.40 espie 1: /* $OpenPackages$ */
1.93 espie 2: /* $OpenBSD$ */
1.6 millert 3: /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */
1.1 deraadt 4:
5: /*
6: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
7: * Copyright (c) 1988, 1989 by Adam de Boor
8: * Copyright (c) 1989 by Berkeley Softworks
9: * All rights reserved.
10: *
11: * This code is derived from software contributed to Berkeley by
12: * Adam de Boor.
13: *
14: * Redistribution and use in source and binary forms, with or without
15: * modification, are permitted provided that the following conditions
16: * are met:
17: * 1. Redistributions of source code must retain the above copyright
18: * notice, this list of conditions and the following disclaimer.
19: * 2. Redistributions in binary form must reproduce the above copyright
20: * notice, this list of conditions and the following disclaimer in the
21: * documentation and/or other materials provided with the distribution.
1.55 millert 22: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: */
38:
39: /*-
40: * job.c --
41: * handle the creation etc. of our child processes.
42: *
43: * Interface:
1.40 espie 44: * Job_Make Start the creation of the given target.
1.1 deraadt 45: *
1.40 espie 46: * Job_CatchChildren Check for and handle the termination of any
47: * children. This must be called reasonably
48: * frequently to keep the whole make going at
49: * a decent clip, since job table entries aren't
50: * removed until their process is caught this way.
51: *
52: * Job_CatchOutput Print any output our children have produced.
53: * Should also be called fairly frequently to
54: * keep the user informed of what's going on.
55: * If no output is waiting, it will block for
56: * a time given by the SEL_* constants, below,
57: * or until output is ready.
58: *
1.53 jmc 59: * Job_Init Called to initialize this module. in addition,
1.40 espie 60: * any commands attached to the .BEGIN target
61: * are executed before this function returns.
62: * Hence, the makefile must have been parsed
63: * before this function is called.
64: *
65: * Job_End Cleanup any memory used.
66: *
1.41 espie 67: * Job_Full Return true if the job table is filled.
1.40 espie 68: *
1.41 espie 69: * Job_Empty Return true if the job table is completely
1.40 espie 70: * empty.
71: *
72: * Job_Finish Perform any final processing which needs doing.
73: * This includes the execution of any commands
74: * which have been/were attached to the .END
75: * target. It should only be called when the
76: * job table is empty.
77: *
78: * Job_AbortAll Abort all currently running jobs. It doesn't
79: * handle output or do anything for the jobs,
80: * just kills them. It should only be called in
81: * an emergency, as it were.
1.1 deraadt 82: *
1.40 espie 83: * Job_Wait Wait for all currently-running jobs to finish.
1.1 deraadt 84: */
85:
86: #include <sys/types.h>
87: #include <sys/wait.h>
1.41 espie 88: #include <ctype.h>
89: #include <errno.h>
1.1 deraadt 90: #include <fcntl.h>
1.41 espie 91: #include <signal.h>
1.69 espie 92: #include <stdarg.h>
1.1 deraadt 93: #include <stdio.h>
1.42 espie 94: #include <stdlib.h>
1.1 deraadt 95: #include <string.h>
1.41 espie 96: #include <unistd.h>
97: #include "config.h"
98: #include "defines.h"
1.1 deraadt 99: #include "job.h"
1.63 espie 100: #include "engine.h"
1.1 deraadt 101: #include "pathnames.h"
1.41 espie 102: #include "var.h"
103: #include "targ.h"
104: #include "error.h"
105: #include "lst.h"
106: #include "extern.h"
107: #include "gnode.h"
108: #include "memory.h"
109: #include "make.h"
110:
1.50 espie 111: /*
112: * The SEL_ constants determine the maximum amount of time spent in select
113: * before coming out to see if a child has finished. SEL_SEC is the number of
114: * seconds and SEL_USEC is the number of micro-seconds
115: */
116: #define SEL_SEC 0
117: #define SEL_USEC 500000
118:
119:
120: /*-
121: * Job Table definitions.
122: *
123: * Each job has several things associated with it:
124: * 1) The process id of the child shell
125: * 2) The graph node describing the target being made by this job
1.93 espie 126: * 3) An FILE* for writing out the commands. This is only
1.50 espie 127: * used before the job is actually started.
1.93 espie 128: * 4) Things used for handling the shell's output.
1.76 espie 129: * the output is being caught via a pipe and
1.50 espie 130: * the descriptors of our pipe, an array in which output is line
131: * buffered and the current position in that buffer are all
1.78 espie 132: * maintained for each job.
1.93 espie 133: * 5) A word of flags which determine how the module handles errors,
1.50 espie 134: * echoing, etc. for the job
135: *
136: * The job "table" is kept as a linked Lst in 'jobs', with the number of
137: * active jobs maintained in the 'nJobs' variable. At no time will this
138: * exceed the value of 'maxJobs', initialized by the Job_Init function.
139: *
140: * When a job is finished, the Make_Update function is called on each of the
141: * parents of the node which was just remade. This takes care of the upward
142: * traversal of the dependency graph.
143: */
144: #define JOB_BUFSIZE 1024
1.101 espie 145: struct job_pipe {
146: int fd;
147: char buffer[JOB_BUFSIZE];
148: size_t pos;
149: };
150:
1.50 espie 151: typedef struct Job_ {
1.51 mpech 152: pid_t pid; /* The child's process ID */
1.50 espie 153: GNode *node; /* The target the child is making */
154: short flags; /* Flags to control treatment of job */
155: #define JOB_IGNERR 0x001 /* Ignore non-zero exits */
156: #define JOB_SILENT 0x002 /* no output */
1.83 espie 157: #define JOB_SPECIAL 0x004 /* Target is a special one. */
1.50 espie 158: #define JOB_RESTART 0x080 /* Job needs to be completely restarted */
1.79 espie 159: #define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped,
160: * for some reason */
161: #define JOB_CONTINUING 0x200 /* We are in the process of resuming this job.
162: * Used to avoid infinite recursion between
163: * JobFinish and JobRestart */
1.101 espie 164: struct job_pipe in[2];
1.50 espie 165: } Job;
166:
1.78 espie 167:
1.40 espie 168: static int aborting = 0; /* why is the make aborting? */
169: #define ABORT_ERROR 1 /* Because of an error */
170: #define ABORT_INTERRUPT 2 /* Because it was interrupted */
171: #define ABORT_WAIT 3 /* Waiting for jobs to finish */
1.1 deraadt 172:
1.40 espie 173: static int maxJobs; /* The most children we can run at once */
1.83 espie 174: static int nJobs; /* The number of children currently running */
1.95 espie 175: static LIST runningJobs; /* The structures that describe them */
1.79 espie 176: static bool jobFull; /* Flag to tell when the job table is full. It
1.83 espie 177: * is set true when nJobs equals maxJobs */
1.40 espie 178: static fd_set *outputsp; /* Set of descriptors of pipes connected to
1.1 deraadt 179: * the output channels of children */
1.8 deraadt 180: static int outputsn;
1.48 espie 181: static GNode *lastNode; /* The node for which output was most recently
1.1 deraadt 182: * produced. */
183: /*
1.50 espie 184: * When JobStart attempts to run a job but isn't allowed to,
1.96 espie 185: * the job is placed on the queuedJobs queue to be run
1.6 millert 186: * when the next job finishes.
1.1 deraadt 187: */
1.96 espie 188: static LIST stoppedJobs;
189: static LIST queuedJobs;
1.101 espie 190: static LIST errorsList;
191: static int errors;
192: struct error_info {
193: int status;
194: char *name;
195: };
196:
1.1 deraadt 197:
198:
199: #if defined(USE_PGRP) && defined(SYSV)
1.40 espie 200: # define KILL(pid, sig) killpg(-(pid), (sig))
1.1 deraadt 201: #else
202: # if defined(USE_PGRP)
1.2 deraadt 203: # define KILL(pid, sig) killpg((pid), (sig))
1.1 deraadt 204: # else
1.2 deraadt 205: # define KILL(pid, sig) kill((pid), (sig))
1.1 deraadt 206: # endif
207: #endif
208:
1.6 millert 209: /*
1.2 deraadt 210: * Grmpf... There is no way to set bits of the wait structure
211: * anymore with the stupid W*() macros. I liked the union wait
212: * stuff much more. So, we devise our own macros... This is
213: * really ugly, use dramamine sparingly. You have been warned.
214: */
215: #define W_SETMASKED(st, val, fun) \
216: { \
217: int sh = (int) ~0; \
218: int mask = fun(sh); \
219: \
220: for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \
221: continue; \
222: *(st) = (*(st) & ~mask) | ((val) << sh); \
223: }
224:
225: #define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG)
226: #define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS)
227:
228:
1.93 espie 229: static void pass_signal_to_job(void *, void *);
230: static void handle_all_signals(void);
231: static void handle_signal(int);
1.40 espie 232: static int JobCmpPid(void *, void *);
233: static void JobClose(Job *);
1.101 espie 234: static void JobFinish(Job *, int);
235: static void JobExec(Job *);
1.40 espie 236: static void JobRestart(Job *);
1.97 espie 237: static void JobStart(GNode *, int);
1.40 espie 238: static void JobInterrupt(int, int);
239: static void JobRestartJobs(void);
1.84 espie 240: static void debug_printf(const char *, ...);
1.98 espie 241: static Job *prepare_job(GNode *, int);
1.96 espie 242: static void start_queued_job(Job *);
1.105 ! espie 243: static void banner(Job *, FILE *);
1.101 espie 244: static void print_partial_buffer(struct job_pipe *, Job *, FILE *, size_t);
245: static void print_partial_buffer_and_shift(struct job_pipe *, Job *, FILE *,
246: size_t);
247: static bool print_complete_lines(struct job_pipe *, Job *, FILE *, size_t);
248: static void prepare_pipe(struct job_pipe *, int *);
249: static void handle_job_output(Job *, int, bool);
250: static void register_error(int, Job *);
1.93 espie 251:
1.101 espie 252: static void
253: register_error(int status, Job *job)
254: {
255: struct error_info *p;
1.1 deraadt 256:
1.101 espie 257: errors++;
258: p = emalloc(sizeof(struct error_info));
259: p->status = status;
260: p->name = job->node->name;
261: if (p)
262: Lst_AtEnd(&errorsList, p);
263: }
1.93 espie 264:
1.101 espie 265: void
266: print_errors()
1.88 espie 267: {
1.101 espie 268: LstNode ln;
269: struct error_info *p;
1.88 espie 270:
1.101 espie 271: for (ln = Lst_First(&errorsList); ln != NULL; ln = Lst_Adv(ln)) {
272: p = (struct error_info *)Lst_Datum(ln);
273: if (WIFEXITED(p->status)) {
274: Error("\tExit status %d in target %s",
275: WEXITSTATUS(p->status), p->name);
276: } else if (WIFSIGNALED(p->status)) {
277: Error("\tReceived signal %d in target s",
278: WTERMSIG(p->status), p->name);
279: } else {
280: Error("\tStatus %d in target %s", p->status, p->name);
281: }
282: }
1.88 espie 283: }
284:
1.57 espie 285: static void
1.105 ! espie 286: banner(Job *job, FILE *out)
1.57 espie 287: {
1.101 espie 288: if (job->node != lastNode) {
1.105 ! espie 289: if (DEBUG(JOBBANNER))
1.101 espie 290: (void)fprintf(out, "--- %s ---\n", job->node->name);
291: lastNode = job->node;
1.57 espie 292: }
293: }
294:
295: static void
1.93 espie 296: handle_all_signals()
1.57 espie 297: {
1.93 espie 298: if (got_signal)
299: got_signal = 0;
300: else
301: return;
302:
1.57 espie 303: if (got_SIGINT) {
304: got_SIGINT=0;
1.93 espie 305: handle_signal(SIGINT);
1.57 espie 306: }
307: if (got_SIGHUP) {
308: got_SIGHUP=0;
1.93 espie 309: handle_signal(SIGHUP);
1.57 espie 310: }
311: if (got_SIGQUIT) {
312: got_SIGQUIT=0;
1.93 espie 313: handle_signal(SIGQUIT);
1.57 espie 314: }
315: if (got_SIGTERM) {
316: got_SIGTERM=0;
1.93 espie 317: handle_signal(SIGTERM);
1.57 espie 318: }
319: if (got_SIGTSTP) {
320: got_SIGTSTP=0;
1.93 espie 321: handle_signal(SIGTSTP);
1.57 espie 322: }
323: if (got_SIGTTOU) {
324: got_SIGTTOU=0;
1.93 espie 325: handle_signal(SIGTTOU);
1.57 espie 326: }
327: if (got_SIGTTIN) {
328: got_SIGTTIN=0;
1.93 espie 329: handle_signal(SIGTTIN);
1.57 espie 330: }
331: if (got_SIGWINCH) {
332: got_SIGWINCH=0;
1.93 espie 333: handle_signal(SIGWINCH);
1.57 espie 334: }
335: }
336:
1.1 deraadt 337: /*-
338: *-----------------------------------------------------------------------
339: * JobCondPassSig --
1.50 espie 340: * Pass a signal to a job if USE_PGRP
1.1 deraadt 341: * is defined.
342: *
343: * Side Effects:
344: * None, except the job may bite it.
345: *-----------------------------------------------------------------------
346: */
1.27 espie 347: static void
1.93 espie 348: pass_signal_to_job(void *jobp, /* Job to biff */
1.56 espie 349: void *signop) /* Signal to send it */
1.1 deraadt 350: {
1.66 espie 351: Job *job = (Job *)jobp;
352: int signo = *(int *)signop;
353: if (DEBUG(JOB)) {
354: (void)fprintf(stdout,
1.93 espie 355: "pass_signal_to_job passing signal %d to child %ld.\n",
1.66 espie 356: signo, (long)job->pid);
357: (void)fflush(stdout);
358: }
359: KILL(job->pid, signo);
1.1 deraadt 360: }
361:
362: /*-
363: *-----------------------------------------------------------------------
1.94 espie 364: * handle_signal --
1.68 espie 365: * Pass a signal to all local jobs if USE_PGRP is defined,
1.50 espie 366: * then die ourselves.
1.1 deraadt 367: *
368: * Side Effects:
369: * We die by the same signal.
370: *-----------------------------------------------------------------------
371: */
372: static void
1.93 espie 373: handle_signal(int signo) /* The signal number we've received */
1.1 deraadt 374: {
1.66 espie 375: sigset_t nmask, omask;
376: struct sigaction act;
1.6 millert 377:
1.66 espie 378: if (DEBUG(JOB)) {
1.93 espie 379: (void)fprintf(stdout, "handle_signal(%d) called.\n", signo);
1.66 espie 380: (void)fflush(stdout);
381: }
1.95 espie 382: Lst_ForEach(&runningJobs, pass_signal_to_job, &signo);
1.66 espie 383:
384: /*
385: * Deal with proper cleanup based on the signal received. We only run
386: * the .INTERRUPT target if the signal was in fact an interrupt. The
387: * other three termination signals are more of a "get out *now*"
388: * command.
389: */
390: if (signo == SIGINT) {
391: JobInterrupt(true, signo);
392: } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) {
393: JobInterrupt(false, signo);
394: }
1.1 deraadt 395:
1.66 espie 396: /*
397: * Leave gracefully if SIGQUIT, rather than core dumping.
398: */
399: if (signo == SIGQUIT) {
400: Finish(0);
401: }
1.6 millert 402:
1.66 espie 403: /*
404: * Send ourselves the signal now we've given the message to everyone
405: * else. Note we block everything else possible while we're getting
406: * the signal. This ensures that all our jobs get continued when we
407: * wake up before we take any other signal.
408: */
409: sigemptyset(&nmask);
410: sigaddset(&nmask, signo);
411: sigprocmask(SIG_SETMASK, &nmask, &omask);
412: memset(&act, 0, sizeof act);
413: act.sa_handler = SIG_DFL;
414: sigemptyset(&act.sa_mask);
415: act.sa_flags = 0;
416: sigaction(signo, &act, NULL);
1.6 millert 417:
1.66 espie 418: if (DEBUG(JOB)) {
419: (void)fprintf(stdout,
1.93 espie 420: "handle_signal passing signal to self, mask = %x.\n",
1.66 espie 421: ~0 & ~(1 << (signo-1)));
422: (void)fflush(stdout);
423: }
424: (void)signal(signo, SIG_DFL);
1.1 deraadt 425:
1.66 espie 426: (void)KILL(getpid(), signo);
1.1 deraadt 427:
1.66 espie 428: signo = SIGCONT;
1.95 espie 429: Lst_ForEach(&runningJobs, pass_signal_to_job, &signo);
1.1 deraadt 430:
1.66 espie 431: (void)sigprocmask(SIG_SETMASK, &omask, NULL);
432: sigprocmask(SIG_SETMASK, &omask, NULL);
433: act.sa_handler = SigHandler;
434: sigaction(signo, &act, NULL);
1.1 deraadt 435: }
436:
437: /*-
438: *-----------------------------------------------------------------------
439: * JobCmpPid --
440: * Compare the pid of the job with the given pid and return 0 if they
441: * are equal. This function is called from Job_CatchChildren via
442: * Lst_Find to find the job descriptor of the finished job.
443: *
444: * Results:
445: * 0 if the pid's match
446: *-----------------------------------------------------------------------
447: */
448: static int
1.56 espie 449: JobCmpPid(void *job, /* job to examine */
450: void *pid) /* process id desired */
1.1 deraadt 451: {
1.66 espie 452: return *(pid_t *)pid - ((Job *)job)->pid;
1.1 deraadt 453: }
454:
1.69 espie 455: static void
1.84 espie 456: debug_printf(const char *fmt, ...)
457: {
458: if (DEBUG(JOB)) {
459: va_list va;
460:
461: va_start(va, fmt);
462: (void)vfprintf(stdout, fmt, va);
463: fflush(stdout);
464: va_end(va);
465: }
466: }
467:
1.1 deraadt 468: /*-
469: *-----------------------------------------------------------------------
1.2 deraadt 470: * JobClose --
471: * Called to close both input and output pipes when a job is finished.
472: *
473: * Side Effects:
474: * The file descriptors associated with the job are closed.
475: *-----------------------------------------------------------------------
476: */
477: static void
1.56 espie 478: JobClose(Job *job)
1.2 deraadt 479: {
1.101 espie 480: int i;
481:
482: for (i = 0; i < 2; i++) {
483: FD_CLR(job->in[i].fd, outputsp);
484: handle_job_output(job, i, true);
485: (void)close(job->in[i].fd);
1.66 espie 486: }
1.1 deraadt 487: }
488:
489: /*-
490: *-----------------------------------------------------------------------
491: * JobFinish --
492: * Do final processing for the given job including updating
493: * parents and starting new jobs as available/necessary. Note
494: * that we pay no attention to the JOB_IGNERR flag here.
495: * This is because when we're called because of a noexecute flag
496: * or something, jstat.w_status is 0 and when called from
497: * Job_CatchChildren, the status is zeroed if it s/b ignored.
498: *
499: * Side Effects:
500: * Some nodes may be put on the toBeMade queue.
1.78 espie 501: * Final commands for the job are placed on end_node.
1.1 deraadt 502: *
1.6 millert 503: * If we got an error and are aborting (aborting == ABORT_ERROR) and
1.1 deraadt 504: * the job list is now empty, we are done for the day.
1.101 espie 505: * If we recognized an error we set the aborting flag
1.1 deraadt 506: * to ABORT_ERROR so no more jobs will be started.
507: *-----------------------------------------------------------------------
508: */
509: /*ARGSUSED*/
510: static void
1.101 espie 511: JobFinish(Job *job, int status)
1.2 deraadt 512: {
1.78 espie 513: bool done;
1.2 deraadt 514:
1.101 espie 515: if ((WIFEXITED(status) &&
516: WEXITSTATUS(status) != 0 && !(job->flags & JOB_IGNERR)) ||
517: (WIFSIGNALED(status) && WTERMSIG(status) != SIGCONT)) {
1.66 espie 518: /*
519: * If it exited non-zero and either we're doing things our
520: * way or we're not ignoring errors, the job is finished.
521: * Similarly, if the shell died because of a signal
522: * the job is also finished. In these
523: * cases, finish out the job's output before printing the exit
524: * status...
525: */
526: JobClose(job);
527: done = true;
1.101 espie 528: } else if (WIFEXITED(status)) {
1.66 espie 529: /*
530: * Deal with ignored errors in -B mode. We need to print a
531: * message telling of the ignored error as well as setting
532: * status.w_status to 0 so the next command gets run. To do
533: * this, we set done to be true if in -B mode and the job
534: * exited non-zero.
535: */
1.101 espie 536: done = WEXITSTATUS(status) != 0;
1.66 espie 537: /*
538: * Old comment said: "Note we don't want to close down any of
539: * the streams until we know we're at the end." But we do.
540: * Otherwise when are we going to print the rest of the stuff?
541: */
542: JobClose(job);
543: } else {
544: /*
545: * No need to close things down or anything.
546: */
547: done = false;
1.1 deraadt 548: }
1.6 millert 549:
1.66 espie 550: if (done ||
1.101 espie 551: WIFSTOPPED(status) ||
552: (WIFSIGNALED(status) && WTERMSIG(status) == SIGCONT) ||
1.66 espie 553: DEBUG(JOB)) {
1.101 espie 554: if (WIFEXITED(status)) {
1.84 espie 555: debug_printf("Process %ld exited.\n", (long)job->pid);
1.101 espie 556: if (WEXITSTATUS(status) != 0) {
1.105 ! espie 557: banner(job, stdout);
1.101 espie 558: (void)fprintf(stdout, "*** Error code %d%s\n",
559: WEXITSTATUS(status),
1.68 espie 560: (job->flags & JOB_IGNERR) ? "(ignored)" :
1.66 espie 561: "");
562:
563: if (job->flags & JOB_IGNERR) {
1.101 espie 564: status = 0;
1.66 espie 565: }
566: } else if (DEBUG(JOB)) {
1.105 ! espie 567: banner(job, stdout);
1.101 espie 568: (void)fprintf(stdout,
1.66 espie 569: "*** Completed successfully\n");
570: }
1.101 espie 571: } else if (WIFSTOPPED(status)) {
1.84 espie 572: debug_printf("Process %ld stopped.\n", (long)job->pid);
1.105 ! espie 573: banner(job, stdout);
1.101 espie 574: (void)fprintf(stdout, "*** Stopped -- signal %d\n",
575: WSTOPSIG(status));
1.66 espie 576: job->flags |= JOB_RESUME;
577: Lst_AtEnd(&stoppedJobs, job);
1.101 espie 578: (void)fflush(stdout);
1.66 espie 579: return;
1.101 espie 580: } else if (WTERMSIG(status) == SIGCONT) {
1.66 espie 581: /*
582: * If the beastie has continued, shift the Job from the
583: * stopped list to the running one (or re-stop it if
584: * concurrency is exceeded) and go and get another
585: * child.
586: */
587: if (job->flags & (JOB_RESUME|JOB_RESTART)) {
1.105 ! espie 588: banner(job, stdout);
1.101 espie 589: (void)fprintf(stdout, "*** Continued\n");
1.66 espie 590: }
591: if (!(job->flags & JOB_CONTINUING)) {
1.84 espie 592: debug_printf(
593: "Warning: "
594: "process %ld was not continuing.\n",
595: (long)job->pid);
1.66 espie 596: #if 0
597: /*
598: * We don't really want to restart a job from
599: * scratch just because it continued,
600: * especially not without killing the
601: * continuing process! That's why this is
602: * ifdef'ed out. FD - 9/17/90
603: */
604: JobRestart(job);
1.2 deraadt 605: #endif
1.66 espie 606: }
607: job->flags &= ~JOB_CONTINUING;
1.95 espie 608: Lst_AtEnd(&runningJobs, job);
1.67 espie 609: nJobs++;
1.84 espie 610: debug_printf("Process %ld is continuing locally.\n",
611: (long)job->pid);
1.66 espie 612: if (nJobs == maxJobs) {
613: jobFull = true;
1.84 espie 614: debug_printf("Job queue is full.\n");
1.66 espie 615: }
1.101 espie 616: (void)fflush(stdout);
1.66 espie 617: return;
618: } else {
1.105 ! espie 619: banner(job, stdout);
1.101 espie 620: (void)fprintf(stdout, "*** Signal %d\n",
621: WTERMSIG(status));
1.40 espie 622: }
1.66 espie 623:
1.101 espie 624: (void)fflush(stdout);
1.1 deraadt 625: }
626:
1.85 espie 627: done = true;
1.1 deraadt 628:
1.66 espie 629: if (done &&
630: aborting != ABORT_ERROR &&
631: aborting != ABORT_INTERRUPT &&
1.101 espie 632: status == 0) {
1.66 espie 633: /* As long as we aren't aborting and the job didn't return a
634: * non-zero status that we shouldn't ignore, we call
1.101 espie 635: * Make_Update to update the parents. */
1.66 espie 636: job->node->made = MADE;
637: Make_Update(job->node);
638: free(job);
1.101 espie 639: } else if (status != 0) {
640: register_error(status, job);
1.66 espie 641: free(job);
642: }
1.1 deraadt 643:
1.66 espie 644: JobRestartJobs();
1.1 deraadt 645:
646: /*
1.66 espie 647: * Set aborting if any error.
1.1 deraadt 648: */
1.101 espie 649: if (errors && !keepgoing &&
650: aborting != ABORT_INTERRUPT) {
1.66 espie 651: /*
652: * If we found any errors in this batch of children and the -k
653: * flag wasn't given, we set the aborting flag so no more jobs
654: * get started.
655: */
656: aborting = ABORT_ERROR;
657: }
1.6 millert 658:
1.66 espie 659: if (aborting == ABORT_ERROR && Job_Empty()) {
660: /*
661: * If we are aborting and the job table is now empty, we finish.
662: */
663: Finish(errors);
664: }
1.1 deraadt 665: }
666:
1.101 espie 667: static void
668: prepare_pipe(struct job_pipe *p, int *fd)
669: {
670: p->pos = 0;
671: (void)fcntl(fd[0], F_SETFD, FD_CLOEXEC);
672: p->fd = fd[0];
673: close(fd[1]);
674:
675: if (outputsp == NULL || p->fd > outputsn) {
676: int fdn, ofdn;
677: fd_set *tmp;
678:
679: fdn = howmany(p->fd+1, NFDBITS);
680: ofdn = outputsn ? howmany(outputsn+1, NFDBITS) : 0;
681:
682: if (fdn != ofdn) {
683: tmp = recalloc(outputsp, fdn, sizeof(fd_mask));
684: if (tmp == NULL)
685: return;
686: outputsp = tmp;
687: }
688: outputsn = p->fd;
689: }
690: fcntl(p->fd, F_SETFL, O_NONBLOCK);
691: FD_SET(p->fd, outputsp);
692: }
693:
1.1 deraadt 694: /*-
695: *-----------------------------------------------------------------------
696: * JobExec --
697: * Execute the shell for the given job. Called from JobStart and
698: * JobRestart.
699: *
700: * Side Effects:
701: * A shell is executed, outputs is altered and the Job structure added
702: * to the job table.
703: *-----------------------------------------------------------------------
704: */
705: static void
1.101 espie 706: JobExec(Job *job)
1.1 deraadt 707: {
1.66 espie 708: pid_t cpid; /* ID of new child */
1.101 espie 709: int fds[4];
710: int *fdout = fds;
711: int *fderr = fds+2;
712: int result;
713: int i;
1.6 millert 714:
1.66 espie 715: if (DEBUG(JOB)) {
716: (void)fprintf(stdout, "Running %s\n", job->node->name);
717: (void)fflush(stdout);
1.1 deraadt 718: }
1.6 millert 719:
1.66 espie 720: /*
721: * Some jobs produce no output and it's disconcerting to have
722: * no feedback of their running (since they produce no output, the
723: * banner with their name in it never appears). This is an attempt to
724: * provide that feedback, even if nothing follows it.
725: */
1.105 ! espie 726: banner(job, stdout);
1.101 espie 727:
728: setup_engine();
729:
730: /* Create the pipe by which we'll get the shell's output.
731: */
732: if (pipe(fdout) == -1)
733: Punt("Cannot create pipe: %s", strerror(errno));
1.1 deraadt 734:
1.101 espie 735: if (pipe(fderr) == -1)
736: Punt("Cannot create pipe: %s", strerror(errno));
1.94 espie 737:
1.66 espie 738: if ((cpid = fork()) == -1) {
739: Punt("Cannot fork");
740: } else if (cpid == 0) {
1.104 espie 741: supervise_jobs = false;
1.101 espie 742: /* standard pipe code to route stdout and stderr */
743: close(fdout[0]);
744: if (dup2(fdout[1], 1) == -1)
745: Punt("Cannot dup2(outPipe): %s", strerror(errno));
746: if (fdout[1] != 1)
747: close(fdout[1]);
748: close(fderr[0]);
749: if (dup2(fderr[1], 2) == -1)
750: Punt("Cannot dup2(errPipe): %s", strerror(errno));
751: if (fderr[1] != 2)
752: close(fderr[1]);
1.1 deraadt 753:
754: #ifdef USE_PGRP
1.66 espie 755: /*
756: * We want to switch the child into a different process family
757: * so we can kill it and all its descendants in one fell swoop,
758: * by killing its process family, but not commit suicide.
759: */
1.2 deraadt 760: # if defined(SYSV)
1.66 espie 761: (void)setsid();
1.2 deraadt 762: # else
1.66 espie 763: (void)setpgid(0, getpid());
1.2 deraadt 764: # endif
765: #endif /* USE_PGRP */
1.1 deraadt 766:
1.101 espie 767: /* most cases won't return, but will exit directly */
768: result = run_gnode(job->node, 1);
769: switch(result) {
770: case MADE:
771: exit(0);
772: case ERROR:
773: exit(1);
774: default:
775: fprintf(stderr,
776: "Could not run gnode, returned %d\n", result);
777: exit(1);
778: }
1.66 espie 779: } else {
1.104 espie 780: supervise_jobs = true;
1.66 espie 781: job->pid = cpid;
782:
1.101 espie 783: /* we set the current position in the buffers to the beginning
1.87 espie 784: * and mark another stream to watch in the outputs mask
785: */
1.101 espie 786: for (i = 0; i < 2; i++)
787: prepare_pipe(&job->in[i], fds+2*i);
1.1 deraadt 788: }
789:
1.48 espie 790: /*
1.66 espie 791: * Now the job is actually running, add it to the table.
1.48 espie 792: */
1.67 espie 793: nJobs++;
1.95 espie 794: Lst_AtEnd(&runningJobs, job);
1.66 espie 795: if (nJobs == maxJobs) {
796: jobFull = true;
1.1 deraadt 797: }
798: }
799:
1.96 espie 800: static void
801: start_queued_job(Job *job)
802: {
803: if (DEBUG(JOB)) {
804: (void)fprintf(stdout, "Restarting %s...",
805: job->node->name);
806: (void)fflush(stdout);
807: }
808: if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) {
809: /*
810: * Can't be exported and not allowed to run locally --
811: * put it back on the hold queue and mark the table
812: * full
813: */
814: debug_printf("holding\n");
815: Lst_AtFront(&stoppedJobs, job);
816: jobFull = true;
817: debug_printf("Job queue is full.\n");
818: return;
819: } else {
820: /*
821: * Job may be run locally.
822: */
823: debug_printf("running locally\n");
824: }
1.101 espie 825: JobExec(job);
1.96 espie 826: }
827:
1.1 deraadt 828: /*-
829: *-----------------------------------------------------------------------
830: * JobRestart --
1.6 millert 831: * Restart a job that stopped for some reason.
1.1 deraadt 832: *
833: * Side Effects:
834: * jobFull will be set if the job couldn't be run.
835: *-----------------------------------------------------------------------
836: */
837: static void
1.56 espie 838: JobRestart(Job *job)
1.1 deraadt 839: {
1.66 espie 840: if (job->flags & JOB_RESTART) {
1.96 espie 841: start_queued_job(job);
1.66 espie 842: } else {
1.1 deraadt 843: /*
1.66 espie 844: * The job has stopped and needs to be restarted. Why it
845: * stopped, we don't know...
1.1 deraadt 846: */
1.84 espie 847: debug_printf("Resuming %s...", job->node->name);
1.83 espie 848: if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) &&
849: maxJobs == 0)) && nJobs != maxJobs) {
1.66 espie 850: /*
1.79 espie 851: * If we haven't reached the concurrency limit already
1.83 espie 852: * (or maxJobs is 0), it's ok to resume the job.
1.66 espie 853: */
854: bool error;
1.101 espie 855: int status = 0;
1.66 espie 856:
857: error = KILL(job->pid, SIGCONT) != 0;
858:
859: if (!error) {
860: /*
861: * Make sure the user knows we've continued the
862: * beast and actually put the thing in the job
863: * table.
864: */
865: job->flags |= JOB_CONTINUING;
866: W_SETTERMSIG(&status, SIGCONT);
1.101 espie 867: JobFinish(job, status);
1.66 espie 868:
869: job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
1.84 espie 870: debug_printf("done\n");
1.66 espie 871: } else {
872: Error("couldn't resume %s: %s",
873: job->node->name, strerror(errno));
874: W_SETEXITSTATUS(&status, 1);
1.101 espie 875: JobFinish(job, status);
1.66 espie 876: }
877: } else {
878: /*
879: * Job cannot be restarted. Mark the table as full and
880: * place the job back on the list of stopped jobs.
881: */
1.84 espie 882: debug_printf("table full\n");
1.66 espie 883: Lst_AtFront(&stoppedJobs, job);
884: jobFull = true;
1.84 espie 885: debug_printf("Job queue is full.\n");
1.1 deraadt 886: }
887: }
888: }
889:
1.98 espie 890: static Job *
891: prepare_job(GNode *gn, int flags)
1.78 espie 892: {
893: Job *job; /* new job descriptor */
894: bool cmdsOK; /* true if the nodes commands were all right */
895: bool noExec; /* Set true if we decide not to run the job */
1.66 espie 896:
1.86 espie 897: job = emalloc(sizeof(Job));
898: if (job == NULL) {
899: Punt("JobStart out of memory");
1.1 deraadt 900: }
901:
1.66 espie 902: job->node = gn;
1.1 deraadt 903:
904: /*
1.66 espie 905: * Set the initial value of the flags for this job based on the global
906: * ones and the node's attributes... Any flags supplied by the caller
907: * are also added to the field.
1.1 deraadt 908: */
1.87 espie 909: job->flags = flags;
1.66 espie 910: if (Targ_Ignore(gn)) {
911: job->flags |= JOB_IGNERR;
912: }
913: if (Targ_Silent(gn)) {
914: job->flags |= JOB_SILENT;
1.1 deraadt 915: }
1.6 millert 916:
1.1 deraadt 917: /*
1.66 espie 918: * Check the commands now so any attributes from .DEFAULT have a chance
919: * to migrate to the node
1.1 deraadt 920: */
1.87 espie 921: cmdsOK = Job_CheckCommands(gn, Error);
1.1 deraadt 922:
1.66 espie 923: if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {
924: /*
925: * We're serious here, but if the commands were bogus, we're
926: * also dead...
927: */
928: if (!cmdsOK) {
929: DieHorribly();
930: }
1.6 millert 931:
1.101 espie 932: if (Lst_IsEmpty(&gn->commands))
933: noExec = true;
934: else
935: noExec = false;
1.66 espie 936:
1.101 espie 937: } else if (noExecute) {
938: if (!cmdsOK || Lst_IsEmpty(&gn->commands))
1.85 espie 939: noExec = true;
1.101 espie 940: else
941: noExec = false;
1.66 espie 942: } else {
943: /*
944: * Just touch the target and note that no shell should be
1.101 espie 945: * executed. Check
1.66 espie 946: * the commands, too, but don't die if they're no good -- it
947: * does no harm to keep working up the graph.
1.30 espie 948: */
1.87 espie 949: Job_Touch(gn, job->flags & JOB_SILENT);
1.41 espie 950: noExec = true;
1.1 deraadt 951: }
1.66 espie 952:
1.1 deraadt 953: /*
1.66 espie 954: * If we're not supposed to execute a shell, don't.
1.1 deraadt 955: */
1.66 espie 956: if (noExec) {
957: /*
958: * We only want to work our way up the graph if we aren't here
959: * because the commands for the job were no good.
960: */
961: if (cmdsOK) {
962: if (aborting == 0) {
1.102 espie 963: job->node->made = MADE;
1.66 espie 964: Make_Update(job->node);
965: }
966: }
1.99 espie 967: free(job);
968: return NULL;
1.1 deraadt 969: } else {
1.98 espie 970: return job;
1.1 deraadt 971: }
1.98 espie 972: }
1.1 deraadt 973:
1.98 espie 974: /*-
975: *-----------------------------------------------------------------------
976: * JobStart --
977: * Start a target-creation process going for the target described
978: * by the graph node gn.
979: *
980: * Side Effects:
981: * A new Job node is created and added to the list of running
982: * jobs. PMake is forked and a child shell created.
983: *-----------------------------------------------------------------------
984: */
985: static void
986: JobStart(GNode *gn, /* target to create */
987: int flags) /* flags for the job to override normal ones.
988: * e.g. JOB_SPECIAL */
989: {
990: Job *job;
991: job = prepare_job(gn, flags);
992: if (!job)
993: return;
1.83 espie 994: if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) &&
995: maxJobs != 0) {
1.79 espie 996: /*
997: * The job can only be run locally, but we've hit the limit of
998: * local concurrency, so put the job on hold until some other
999: * job finishes. Note that the special jobs (.BEGIN, .INTERRUPT
1000: * and .END) may be run locally even when the local limit has
1.83 espie 1001: * been reached (e.g. when maxJobs == 0), though they will be
1.79 espie 1002: * exported if at all possible. In addition, any target marked
1.83 espie 1003: * with .NOEXPORT will be run locally if maxJobs is 0.
1.66 espie 1004: */
1005: jobFull = true;
1.6 millert 1006:
1.84 espie 1007: debug_printf("Can only run job locally.\n");
1.66 espie 1008: job->flags |= JOB_RESTART;
1009: Lst_AtEnd(&stoppedJobs, job);
1.79 espie 1010: } else {
1.83 espie 1011: if (nJobs >= maxJobs) {
1.79 espie 1012: /*
1013: * If we're running this job locally as a special case
1014: * (see above), at least say the table is full.
1015: */
1016: jobFull = true;
1.84 espie 1017: debug_printf("Local job queue is full.\n");
1.79 espie 1018: }
1.101 espie 1019: JobExec(job);
1.1 deraadt 1020: }
1021: }
1022:
1.101 espie 1023: /* Helper functions for JobDoOutput */
1024:
1025:
1.105 ! espie 1026: /* output debugging banner and print characters from 0 to endpos */
1.101 espie 1027: static void
1028: print_partial_buffer(struct job_pipe *p, Job *job, FILE *out, size_t endPos)
1.2 deraadt 1029: {
1.101 espie 1030: size_t i;
1.2 deraadt 1031:
1.105 ! espie 1032: banner(job, out);
1.101 espie 1033: for (i = 0; i < endPos; i++)
1034: putc(p->buffer[i], out);
1035: }
1036:
1037: /* print partial buffer and shift remaining contents */
1038: static void
1039: print_partial_buffer_and_shift(struct job_pipe *p, Job *job, FILE *out,
1040: size_t endPos)
1041: {
1042: size_t i;
1043:
1044: print_partial_buffer(p, job, out, endPos);
1045:
1046: for (i = endPos; i < p->pos; i++)
1047: p->buffer[i-endPos] = p->buffer[i];
1048: p->pos -= endPos;
1049: }
1050:
1051: /* print complete lines, looking back to the limit position
1052: * (stuff before limit was already scanned).
1053: * returns true if something was printed.
1054: */
1055: static bool
1056: print_complete_lines(struct job_pipe *p, Job *job, FILE *out, size_t limit)
1057: {
1058: size_t i;
1059:
1060: for (i = p->pos; i > limit; i--) {
1061: if (p->buffer[i-1] == '\n') {
1062: print_partial_buffer_and_shift(p, job, out, i);
1063: return true;
1.2 deraadt 1064: }
1065: }
1.101 espie 1066: return false;
1.2 deraadt 1067: }
1.1 deraadt 1068: /*-
1069: *-----------------------------------------------------------------------
1.101 espie 1070: * handle_pipe --
1.89 espie 1071: * This functions is called whenever there is something to read on the
1072: * pipe. We collect more output from the given job and store it in the
1.101 espie 1073: * job's outBuf. If this makes up lines, we print it tagged by the job's
1.89 espie 1074: * identifier, as necessary.
1.1 deraadt 1075: *
1076: * Side Effects:
1077: * curPos may be shifted as may the contents of outBuf.
1078: *-----------------------------------------------------------------------
1079: */
1.48 espie 1080: static void
1.101 espie 1081: handle_pipe(struct job_pipe *p,
1082: Job *job, FILE *out, bool finish)
1.66 espie 1083: {
1084: int nr; /* number of bytes read */
1.101 espie 1085: int oldpos; /* optimization */
1.1 deraadt 1086:
1.101 espie 1087: /* want to get everything ? -> we block */
1088: if (finish)
1089: fcntl(p->fd, F_SETFL, 0);
1090:
1091: do {
1092: nr = read(p->fd, &p->buffer[p->pos],
1093: JOB_BUFSIZE - p->pos);
1094: if (nr == -1) {
1095: if (errno == EAGAIN)
1096: break;
1097: if (DEBUG(JOB)) {
1098: perror("JobDoOutput(piperead)");
1099: }
1.66 espie 1100: }
1.101 espie 1101: oldpos = p->pos;
1102: p->pos += nr;
1103: if (!print_complete_lines(p, job, out, oldpos))
1104: if (p->pos == JOB_BUFSIZE) {
1105: print_partial_buffer(p, job, out, p->pos);
1106: p->pos = 0;
1107: }
1108: } while (nr != 0);
1.1 deraadt 1109:
1.101 espie 1110: /* at end of file, we print whatever is left */
1111: if (nr == 0) {
1112: print_partial_buffer(p, job, out, p->pos);
1113: if (p->pos > 0 && p->buffer[p->pos - 1] != '\n')
1114: putchar('\n');
1115: p->pos = 0;
1.76 espie 1116: }
1.101 espie 1117: }
1.6 millert 1118:
1.101 espie 1119: static void
1120: handle_job_output(Job *job, int i, bool finish)
1121: {
1122: handle_pipe(&job->in[i], job, i == 0 ? stdout : stderr, finish);
1.1 deraadt 1123: }
1124:
1125: /*-
1126: *-----------------------------------------------------------------------
1127: * Job_CatchChildren --
1128: * Handle the exit of a child. Called from Make_Make.
1129: *
1130: * Side Effects:
1131: * The job descriptor is removed from the list of children.
1132: *
1133: * Notes:
1134: * We do waits, blocking or not, according to the wisdom of our
1135: * caller, until there are no more children to report. For each
1136: * job, call JobFinish to finish things off. This will take care of
1137: * putting jobs on the stoppedJobs queue.
1138: *-----------------------------------------------------------------------
1139: */
1140: void
1.76 espie 1141: Job_CatchChildren()
1.1 deraadt 1142: {
1.78 espie 1143: pid_t pid; /* pid of dead child */
1144: Job *job; /* job descriptor for dead child */
1145: LstNode jnode; /* list element for finding job */
1146: int status; /* Exit/termination status */
1.1 deraadt 1147:
1.66 espie 1148: /*
1149: * Don't even bother if we know there's no one around.
1150: */
1.83 espie 1151: if (nJobs == 0) {
1.66 espie 1152: return;
1.2 deraadt 1153: }
1.6 millert 1154:
1.76 espie 1155: while ((pid = waitpid((pid_t) -1, &status, WNOHANG|WUNTRACED)) > 0) {
1.93 espie 1156: handle_all_signals();
1.84 espie 1157: debug_printf("Process %ld exited or stopped.\n", (long)pid);
1.1 deraadt 1158:
1.95 espie 1159: jnode = Lst_Find(&runningJobs, JobCmpPid, &pid);
1.1 deraadt 1160:
1.18 espie 1161: if (jnode == NULL) {
1.68 espie 1162: if (WIFSIGNALED(status) &&
1.66 espie 1163: (WTERMSIG(status) == SIGCONT)) {
1164: jnode = Lst_Find(&stoppedJobs, JobCmpPid, &pid);
1165: if (jnode == NULL) {
1166: Error("Resumed child (%ld) not in table", (long)pid);
1167: continue;
1168: }
1169: job = (Job *)Lst_Datum(jnode);
1170: Lst_Remove(&stoppedJobs, jnode);
1171: } else {
1172: Error("Child (%ld) not in table?", (long)pid);
1173: continue;
1174: }
1175: } else {
1176: job = (Job *)Lst_Datum(jnode);
1.95 espie 1177: Lst_Remove(&runningJobs, jnode);
1.67 espie 1178: nJobs--;
1.84 espie 1179: if (jobFull)
1180: debug_printf("Job queue is no longer full.\n");
1.66 espie 1181: jobFull = false;
1.1 deraadt 1182: }
1.66 espie 1183:
1.101 espie 1184: JobFinish(job, status);
1.1 deraadt 1185: }
1186: }
1187:
1188: /*-
1189: *-----------------------------------------------------------------------
1190: * Job_CatchOutput --
1191: * Catch the output from our children, if we're using
1192: * pipes do so. Otherwise just block time until we get a
1.6 millert 1193: * signal (most likely a SIGCHLD) since there's no point in
1.1 deraadt 1194: * just spinning when there's nothing to do and the reaping
1.6 millert 1195: * of a child can wait for a while.
1.1 deraadt 1196: *
1197: * Side Effects:
1198: * Output is read from pipes if we're piping.
1199: * -----------------------------------------------------------------------
1200: */
1201: void
1.56 espie 1202: Job_CatchOutput(void)
1.1 deraadt 1203: {
1.66 espie 1204: int nfds;
1205: struct timeval timeout;
1206: LstNode ln;
1207: Job *job;
1.101 espie 1208: int i;
1.66 espie 1209:
1.76 espie 1210: int count = howmany(outputsn+1, NFDBITS) * sizeof(fd_mask);
1211: fd_set *readfdsp = malloc(count);
1.91 espie 1212:
1.77 espie 1213: (void)fflush(stdout);
1.76 espie 1214: if (readfdsp == NULL)
1215: return;
1216:
1217: memcpy(readfdsp, outputsp, count);
1218: timeout.tv_sec = SEL_SEC;
1219: timeout.tv_usec = SEL_USEC;
1.66 espie 1220:
1.91 espie 1221: nfds = select(outputsn+1, readfdsp, NULL, NULL, &timeout);
1.93 espie 1222: handle_all_signals();
1.91 espie 1223: if (nfds > 0) {
1.95 espie 1224: for (ln = Lst_First(&runningJobs); nfds && ln != NULL;
1.76 espie 1225: ln = Lst_Adv(ln)) {
1226: job = (Job *)Lst_Datum(ln);
1.101 espie 1227: for (i = 0; i < 2; i++) {
1228: if (FD_ISSET(job->in[i].fd, readfdsp)) {
1229: handle_job_output(job, i, false);
1230: nfds--;
1231: }
1.66 espie 1232: }
1.1 deraadt 1233: }
1234: }
1.76 espie 1235: free(readfdsp);
1.1 deraadt 1236: }
1237:
1238: /*-
1239: *-----------------------------------------------------------------------
1240: * Job_Make --
1241: * Start the creation of a target. Basically a front-end for
1242: * JobStart used by the Make module.
1243: *
1244: * Side Effects:
1245: * Another job is started.
1246: *-----------------------------------------------------------------------
1247: */
1248: void
1.56 espie 1249: Job_Make(GNode *gn)
1.1 deraadt 1250: {
1.86 espie 1251: (void)JobStart(gn, 0);
1.1 deraadt 1252: }
1253:
1254: /*-
1255: *-----------------------------------------------------------------------
1256: * Job_Init --
1257: * Initialize the process module
1258: *
1259: * Side Effects:
1260: * lists and counters are initialized
1261: *-----------------------------------------------------------------------
1262: */
1263: void
1.83 espie 1264: Job_Init(int maxproc)
1.1 deraadt 1265: {
1.95 espie 1266: Static_Lst_Init(&runningJobs);
1.66 espie 1267: Static_Lst_Init(&stoppedJobs);
1.96 espie 1268: Static_Lst_Init(&queuedJobs);
1.101 espie 1269: Static_Lst_Init(&errorsList);
1.66 espie 1270: maxJobs = maxproc;
1.79 espie 1271: nJobs = 0;
1.66 espie 1272: jobFull = false;
1.101 espie 1273: errors = 0;
1.66 espie 1274:
1275: aborting = 0;
1.40 espie 1276:
1.66 espie 1277: lastNode = NULL;
1.1 deraadt 1278:
1.78 espie 1279: if ((begin_node->type & OP_DUMMY) == 0) {
1.86 espie 1280: JobStart(begin_node, JOB_SPECIAL);
1.66 espie 1281: while (nJobs) {
1282: Job_CatchOutput();
1.76 espie 1283: Job_CatchChildren();
1.66 espie 1284: }
1.1 deraadt 1285: }
1286: }
1287:
1288: /*-
1289: *-----------------------------------------------------------------------
1290: * Job_Full --
1291: * See if the job table is full. It is considered full if it is OR
1292: * if we are in the process of aborting OR if we have
1293: * reached/exceeded our local quota. This prevents any more jobs
1294: * from starting up.
1295: *
1296: * Results:
1.41 espie 1297: * true if the job table is full, false otherwise
1.1 deraadt 1298: *-----------------------------------------------------------------------
1299: */
1.41 espie 1300: bool
1.56 espie 1301: Job_Full(void)
1.1 deraadt 1302: {
1.66 espie 1303: return aborting || jobFull;
1.1 deraadt 1304: }
1305:
1306: /*-
1307: *-----------------------------------------------------------------------
1308: * Job_Empty --
1.40 espie 1309: * See if the job table is empty. Because the local concurrency may
1.1 deraadt 1310: * be set to 0, it is possible for the job table to become empty,
1311: * while the list of stoppedJobs remains non-empty. In such a case,
1312: * we want to restart as many jobs as we can.
1313: *
1314: * Results:
1.41 espie 1315: * true if it is. false if it ain't.
1.1 deraadt 1316: * -----------------------------------------------------------------------
1317: */
1.41 espie 1318: bool
1.56 espie 1319: Job_Empty(void)
1.1 deraadt 1320: {
1.66 espie 1321: if (nJobs == 0) {
1322: if (!Lst_IsEmpty(&stoppedJobs) && !aborting) {
1323: /*
1324: * The job table is obviously not full if it has no
1325: * jobs in it...Try and restart the stopped jobs.
1326: */
1327: jobFull = false;
1328: JobRestartJobs();
1329: return false;
1330: } else {
1331: return true;
1332: }
1.1 deraadt 1333: } else {
1.66 espie 1334: return false;
1.1 deraadt 1335: }
1336: }
1337:
1338: /*-
1339: *-----------------------------------------------------------------------
1340: * JobInterrupt --
1341: * Handle the receipt of an interrupt.
1342: *
1343: * Side Effects:
1344: * All children are killed. Another job will be started if the
1345: * .INTERRUPT target was given.
1346: *-----------------------------------------------------------------------
1347: */
1348: static void
1.56 espie 1349: JobInterrupt(int runINTERRUPT, /* Non-zero if commands for the .INTERRUPT
1.1 deraadt 1350: * target should be executed */
1.66 espie 1351: int signo) /* signal received */
1.1 deraadt 1352: {
1.66 espie 1353: LstNode ln; /* element in job table */
1.78 espie 1354: Job *job; /* job descriptor in that element */
1.66 espie 1355:
1356: aborting = ABORT_INTERRUPT;
1357:
1.95 espie 1358: for (ln = Lst_First(&runningJobs); ln != NULL; ln = Lst_Adv(ln)) {
1.66 espie 1359: job = (Job *)Lst_Datum(ln);
1360:
1361: if (!Targ_Precious(job->node)) {
1362: const char *file = job->node->path == NULL ?
1363: job->node->name : job->node->path;
1364: if (!noExecute && eunlink(file) != -1) {
1365: Error("*** %s removed", file);
1366: }
1367: }
1368: if (job->pid) {
1.84 espie 1369: debug_printf("JobInterrupt passing signal to "
1370: "child %ld.\n", (long)job->pid);
1.66 espie 1371: KILL(job->pid, signo);
1372: }
1.2 deraadt 1373: }
1.1 deraadt 1374:
1.66 espie 1375: if (runINTERRUPT && !touchFlag) {
1.78 espie 1376: if ((interrupt_node->type & OP_DUMMY) == 0) {
1.66 espie 1377: ignoreErrors = false;
1378:
1.101 espie 1379: JobStart(interrupt_node, 0);
1.66 espie 1380: while (nJobs) {
1381: Job_CatchOutput();
1.76 espie 1382: Job_CatchChildren();
1.66 espie 1383: }
1384: }
1.1 deraadt 1385: }
1.66 espie 1386: exit(signo);
1.1 deraadt 1387: }
1388:
1389: /*
1390: *-----------------------------------------------------------------------
1.12 espie 1391: * Job_Finish --
1.1 deraadt 1392: * Do final processing such as the running of the commands
1.6 millert 1393: * attached to the .END target.
1.1 deraadt 1394: *
1395: * Results:
1396: * Number of errors reported.
1.40 espie 1397: *
1.1 deraadt 1398: *-----------------------------------------------------------------------
1399: */
1400: int
1.56 espie 1401: Job_Finish(void)
1.1 deraadt 1402: {
1.78 espie 1403: if (end_node != NULL && !Lst_IsEmpty(&end_node->commands)) {
1.66 espie 1404: if (errors) {
1405: Error("Errors reported so .END ignored");
1406: } else {
1.101 espie 1407: JobStart(end_node, JOB_SPECIAL);
1.1 deraadt 1408:
1.66 espie 1409: while (nJobs) {
1410: Job_CatchOutput();
1.76 espie 1411: Job_CatchChildren();
1.66 espie 1412: }
1413: }
1.1 deraadt 1414: }
1.66 espie 1415: return errors;
1.1 deraadt 1416: }
1417:
1.41 espie 1418: #ifdef CLEANUP
1.12 espie 1419: void
1.56 espie 1420: Job_End(void)
1.12 espie 1421: {
1.41 espie 1422: }
1.13 espie 1423: #endif
1.40 espie 1424:
1.1 deraadt 1425: /*-
1426: *-----------------------------------------------------------------------
1427: * Job_Wait --
1428: * Waits for all running jobs to finish and returns. Sets 'aborting'
1429: * to ABORT_WAIT to prevent other jobs from starting.
1430: *
1431: * Side Effects:
1432: * Currently running jobs finish.
1433: *
1434: *-----------------------------------------------------------------------
1435: */
1436: void
1.56 espie 1437: Job_Wait(void)
1.1 deraadt 1438: {
1.66 espie 1439: aborting = ABORT_WAIT;
1440: while (nJobs != 0) {
1441: Job_CatchOutput();
1.76 espie 1442: Job_CatchChildren();
1.66 espie 1443: }
1444: aborting = 0;
1.1 deraadt 1445: }
1446:
1447: /*-
1448: *-----------------------------------------------------------------------
1449: * Job_AbortAll --
1450: * Abort all currently running jobs without handling output or anything.
1451: * This function is to be called only in the event of a major
1452: * error. Most definitely NOT to be called from JobInterrupt.
1453: *
1454: * Side Effects:
1455: * All children are killed, not just the firstborn
1456: *-----------------------------------------------------------------------
1457: */
1458: void
1.56 espie 1459: Job_AbortAll(void)
1.1 deraadt 1460: {
1.66 espie 1461: LstNode ln; /* element in job table */
1462: Job *job; /* the job descriptor in that element */
1463: int foo;
1.6 millert 1464:
1.66 espie 1465: aborting = ABORT_ERROR;
1.6 millert 1466:
1.66 espie 1467: if (nJobs) {
1.95 espie 1468: for (ln = Lst_First(&runningJobs); ln != NULL;
1469: ln = Lst_Adv(ln)) {
1.66 espie 1470: job = (Job *)Lst_Datum(ln);
1471:
1472: /*
1473: * kill the child process with increasingly drastic
1474: * signals to make darn sure it's dead.
1475: */
1476: KILL(job->pid, SIGINT);
1477: KILL(job->pid, SIGKILL);
1478: }
1.1 deraadt 1479: }
1.6 millert 1480:
1.66 espie 1481: /*
1482: * Catch as many children as want to report in at first, then give up
1483: */
1484: while (waitpid(-1, &foo, WNOHANG) > 0)
1485: continue;
1.2 deraadt 1486: }
1.40 espie 1487:
1.2 deraadt 1488: /*-
1489: *-----------------------------------------------------------------------
1490: * JobRestartJobs --
1491: * Tries to restart stopped jobs if there are slots available.
1492: * Note that this tries to restart them regardless of pending errors.
1493: * It's not good to leave stopped jobs lying around!
1494: *
1495: * Side Effects:
1496: * Resumes(and possibly migrates) jobs.
1497: *-----------------------------------------------------------------------
1498: */
1499: static void
1.56 espie 1500: JobRestartJobs(void)
1.2 deraadt 1501: {
1.66 espie 1502: Job *job;
1.19 espie 1503:
1.66 espie 1504: while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL) {
1.84 espie 1505: debug_printf("Job queue is not full. "
1506: "Restarting a stopped job.\n");
1.66 espie 1507: JobRestart(job);
1.2 deraadt 1508: }
1.1 deraadt 1509: }