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