diff options
Diffstat (limited to 'devel/bmake/files/job.c')
-rw-r--r-- | devel/bmake/files/job.c | 187 |
1 files changed, 140 insertions, 47 deletions
diff --git a/devel/bmake/files/job.c b/devel/bmake/files/job.c index e140b945aab..5427c75f958 100644 --- a/devel/bmake/files/job.c +++ b/devel/bmake/files/job.c @@ -1,4 +1,4 @@ -/* $NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $ */ +/* $NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -70,14 +70,14 @@ */ #ifndef MAKE_NATIVE -static char rcsid[] = "$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $"; +static char rcsid[] = "$NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia Exp $"; #else #include <sys/cdefs.h> #ifndef lint #if 0 static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; #else -__RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $"); +__RCSID("$NetBSD: job.c,v 1.1.1.11 2020/05/24 05:35:52 nia Exp $"); #endif #endif /* not lint */ #endif @@ -102,7 +102,7 @@ __RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $"); * a time given by the SEL_* constants, below, * or until output is ready. * - * Job_Init Called to intialize this module. in addition, + * Job_Init Called to initialize this module. in addition, * any commands attached to the .BEGIN target * are executed before this function returns. * Hence, the makefile must have been parsed @@ -144,7 +144,6 @@ __RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $"); #include <assert.h> #include <errno.h> -#include <fcntl.h> #if !defined(USE_SELECT) && defined(HAVE_POLL_H) #include <poll.h> #else @@ -343,17 +342,14 @@ static Job childExitJob; /* child exit pseudo-job */ #define CHILD_EXIT "." #define DO_JOB_RESUME "R" +static const int npseudojobs = 2; /* number of pseudo-jobs */ + #define TARG_FMT "%s %s ---\n" /* Default format */ #define MESSAGE(fp, gn) \ if (maxJobs != 1 && targPrefix && *targPrefix) \ (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) static sigset_t caught_signals; /* Set of signals we handle */ -#if defined(SYSV) -#define KILLPG(pid, sig) kill(-(pid), (sig)) -#else -#define KILLPG(pid, sig) killpg((pid), (sig)) -#endif static void JobChildSig(int); static void JobContinueSig(int); @@ -374,7 +370,20 @@ static void JobSigLock(sigset_t *); static void JobSigUnlock(sigset_t *); static void JobSigReset(void); -const char *malloc_options="A"; +#if !defined(MALLOC_OPTIONS) +# define MALLOC_OPTIONS "A" +#endif +const char *malloc_options= MALLOC_OPTIONS; + +static unsigned +nfds_per_job(void) +{ +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) + return 2; +#endif + return 1; +} static void job_table_dump(const char *where) @@ -389,6 +398,21 @@ job_table_dump(const char *where) } /* + * Delete the target of a failed, interrupted, or otherwise + * unsuccessful job unless inhibited by .PRECIOUS. + */ +static void +JobDeleteTarget(GNode *gn) +{ + if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) { + char *file = (gn->path == NULL ? gn->name : gn->path); + if (!noExecute && eunlink(file) != -1) { + Error("*** %s removed", file); + } + } +} + +/* * JobSigLock/JobSigUnlock * * Signal lock routines to get exclusive access. Currently used to @@ -410,7 +434,7 @@ static void JobSigUnlock(sigset_t *omaskp) static void JobCreatePipe(Job *job, int minfd) { - int i, fd; + int i, fd, flags; if (pipe(job->jobPipe) == -1) Punt("Cannot create pipe: %s", strerror(errno)); @@ -425,8 +449,10 @@ JobCreatePipe(Job *job, int minfd) } /* Set close-on-exec flag for both */ - (void)fcntl(job->jobPipe[0], F_SETFD, 1); - (void)fcntl(job->jobPipe[1], F_SETFD, 1); + if (fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC) == -1) + Punt("Cannot set close-on-exec: %s", strerror(errno)); + if (fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC) == -1) + Punt("Cannot set close-on-exec: %s", strerror(errno)); /* * We mark the input side of the pipe non-blocking; we poll(2) the @@ -434,8 +460,12 @@ JobCreatePipe(Job *job, int minfd) * race for the token when a new one becomes available, so the read * from the pipe should not block. */ - fcntl(job->jobPipe[0], F_SETFL, - fcntl(job->jobPipe[0], F_GETFL, 0) | O_NONBLOCK); + flags = fcntl(job->jobPipe[0], F_GETFL, 0); + if (flags == -1) + Punt("Cannot get flags: %s", strerror(errno)); + flags |= O_NONBLOCK; + if (fcntl(job->jobPipe[0], F_SETFL, flags) == -1) + Punt("Cannot set flags: %s", strerror(errno)); } /*- @@ -715,7 +745,7 @@ JobPrintCommand(void *cmdp, void *jobp) numCommands += 1; - cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE); + cmdStart = cmd = Var_Subst(NULL, cmd, job->node, VARF_WANTRES); cmdTemplate = "%s\n"; @@ -737,6 +767,7 @@ JobPrintCommand(void *cmdp, void *jobp) * but this one needs to be - use compat mode just for it. */ CompatRunCommand(cmdp, job->node); + free(cmdStart); return 0; } break; @@ -866,8 +897,7 @@ JobPrintCommand(void *cmdp, void *jobp) DBPRINTF(cmdTemplate, cmd); free(cmdStart); - if (escCmd) - free(escCmd); + free(escCmd); if (errOff) { /* * If echoing is already off, there's no point in issuing the @@ -903,7 +933,7 @@ JobPrintCommand(void *cmdp, void *jobp) static int JobSaveCommand(void *cmd, void *gn) { - cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, FALSE); + cmd = Var_Subst(NULL, (char *)cmd, (GNode *)gn, VARF_WANTRES); (void)Lst_AtEnd(postCommands->commands, cmd); return(0); } @@ -1035,6 +1065,9 @@ JobFinish (Job *job, WAIT_T status) if (job->flags & JOB_IGNERR) { WAIT_STATUS(status) = 0; } else { + if (deleteOnError) { + JobDeleteTarget(job->node); + } PrintOnError(job->node, NULL); } } else if (DEBUG(JOB)) { @@ -1052,13 +1085,20 @@ JobFinish (Job *job, WAIT_T status) } (void)printf("*** [%s] Signal %d\n", job->node->name, WTERMSIG(status)); + if (deleteOnError) { + JobDeleteTarget(job->node); + } } (void)fflush(stdout); } #ifdef USE_META if (useMeta) { - meta_job_finish(job); + int x; + + if ((x = meta_job_finish(job)) != 0 && status == 0) { + status = x; + } } #endif @@ -1234,8 +1274,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) */ Make_HandleUse(DEFAULT, gn); Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn, 0); - if (p1) - free(p1); + free(p1); } else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) { /* * The node wasn't the target of an operator we have no .DEFAULT @@ -1357,15 +1396,27 @@ JobExec(Job *job, char **argv) execError("dup2", "job->cmdFILE"); _exit(1); } - (void)fcntl(0, F_SETFD, 0); - (void)lseek(0, (off_t)0, SEEK_SET); + if (fcntl(0, F_SETFD, 0) == -1) { + execError("fcntl clear close-on-exec", "stdin"); + _exit(1); + } + if (lseek(0, (off_t)0, SEEK_SET) == -1) { + execError("lseek to 0", "stdin"); + _exit(1); + } if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { /* * Pass job token pipe to submakes. */ - fcntl(tokenWaitJob.inPipe, F_SETFD, 0); - fcntl(tokenWaitJob.outPipe, F_SETFD, 0); + if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) { + execError("clear close-on-exec", "tokenWaitJob.inPipe"); + _exit(1); + } + if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) { + execError("clear close-on-exec", "tokenWaitJob.outPipe"); + _exit(1); + } } /* @@ -1382,7 +1433,10 @@ JobExec(Job *job, char **argv) * it before routing the shell's error output to the same place as * its standard output. */ - (void)fcntl(1, F_SETFD, 0); + if (fcntl(1, F_SETFD, 0) == -1) { + execError("clear close-on-exec", "stdout"); + _exit(1); + } if (dup2(1, 2) == -1) { execError("dup2", "1, 2"); _exit(1); @@ -1416,6 +1470,12 @@ JobExec(Job *job, char **argv) Trace_Log(JOBSTART, job); +#ifdef USE_META + if (useMeta) { + meta_job_parent(job, cpid); + } +#endif + /* * Set the current position in the buffer to the beginning * and mark another stream to watch in the outputs mask @@ -1598,7 +1658,7 @@ JobStart(GNode *gn, int flags) if (job->cmdFILE == NULL) { Punt("Could not fdopen %s", tfile); } - (void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1); + (void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC); /* * Send the commands to the command file, flush all its buffers then * rewind and remove the thing. @@ -2098,12 +2158,24 @@ Job_CatchOutput(void) if (nready == 0) return; - for (i = 2; i < nfds; i++) { + for (i = npseudojobs*nfds_per_job(); i < nfds; i++) { if (!fds[i].revents) continue; job = jobfds[i]; if (job->job_state == JOB_ST_RUNNING) JobDoOutput(job, FALSE); +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + /* + * With meta mode, we may have activity on the job's filemon + * descriptor too, which at the moment is any pollfd other than + * job->inPollfd. + */ + if (useMeta && job->inPollfd != &fds[i]) { + if (meta_job_event(job) <= 0) { + fds[i].events = 0; /* never mind */ + } + } +#endif if (--nready == 0) return; } @@ -2194,7 +2266,8 @@ Job_SetPrefix(void) Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL, 0); } - targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0); + targPrefix = Var_Subst(NULL, "${" MAKE_JOB_PREFIX "}", + VAR_GLOBAL, VARF_WANTRES); } /*- @@ -2247,9 +2320,11 @@ Job_Init(void) JobCreatePipe(&childExitJob, 3); - /* We can only need to wait for tokens, children and output from each job */ - fds = bmake_malloc(sizeof (*fds) * (2 + maxJobs)); - jobfds = bmake_malloc(sizeof (*jobfds) * (2 + maxJobs)); + /* Preallocate enough for the maximum number of jobs. */ + fds = bmake_malloc(sizeof(*fds) * + (npseudojobs + maxJobs) * nfds_per_job()); + jobfds = bmake_malloc(sizeof(*jobfds) * + (npseudojobs + maxJobs) * nfds_per_job()); /* These are permanent entries and take slots 0 and 1 */ watchfd(&tokenWaitJob); @@ -2401,8 +2476,7 @@ Job_ParseShell(char *line) line++; } - if (shellArgv) - free(UNCONST(shellArgv)); + free(UNCONST(shellArgv)); memset(&newShell, 0, sizeof(newShell)); @@ -2577,12 +2651,7 @@ JobInterrupt(int runINTERRUPT, int signo) gn = job->node; - if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) { - char *file = (gn->path == NULL ? gn->name : gn->path); - if (!noExecute && eunlink(file) != -1) { - Error("*** %s removed", file); - } - } + JobDeleteTarget(gn); if (job->pid) { if (DEBUG(JOB)) { (void)fprintf(debug_file, @@ -2650,8 +2719,7 @@ void Job_End(void) { #ifdef CLEANUP - if (shellArgv) - free(shellArgv); + free(shellArgv); #endif } @@ -2775,6 +2843,14 @@ watchfd(Job *job) jobfds[nfds] = job; job->inPollfd = &fds[nfds]; nfds++; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + fds[nfds].fd = meta_job_fd(job); + fds[nfds].events = fds[nfds].fd == -1 ? 0 : POLLIN; + jobfds[nfds] = job; + nfds++; + } +#endif } static void @@ -2785,6 +2861,18 @@ clearfd(Job *job) Punt("Unwatching unwatched job"); i = job->inPollfd - fds; nfds--; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + /* + * Sanity check: there should be two fds per job, so the job's + * pollfd number should be even. + */ + assert(nfds_per_job() == 2); + if (i % 2) + Punt("odd-numbered fd with meta"); + nfds--; + } +#endif /* * Move last job in table into hole made by dead job. */ @@ -2792,6 +2880,12 @@ clearfd(Job *job) fds[i] = fds[nfds]; jobfds[i] = jobfds[nfds]; jobfds[i]->inPollfd = &fds[i]; +#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) + if (useMeta) { + fds[i + 1] = fds[nfds + 1]; + jobfds[i + 1] = jobfds[nfds + 1]; + } +#endif } job->inPollfd = NULL; } @@ -2850,8 +2944,8 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1) /* Pipe passed in from parent */ tokenWaitJob.inPipe = jp_0; tokenWaitJob.outPipe = jp_1; - (void)fcntl(jp_0, F_SETFD, 1); - (void)fcntl(jp_1, F_SETFD, 1); + (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC); + (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC); return; } @@ -2933,7 +3027,6 @@ Job_TokenWithdraw(void) } if (DEBUG(JOB)) fprintf(debug_file, "(%d) blocked for token\n", getpid()); - wantToken = 1; return FALSE; } |