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