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