summaryrefslogtreecommitdiff
path: root/devel/bmake/files/job.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/bmake/files/job.c')
-rw-r--r--devel/bmake/files/job.c246
1 files changed, 154 insertions, 92 deletions
diff --git a/devel/bmake/files/job.c b/devel/bmake/files/job.c
index c7732eeafa0..e140b945aab 100644
--- a/devel/bmake/files/job.c
+++ b/devel/bmake/files/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.1.1.9 2011/06/18 22:17:58 bsiegert Exp $ */
+/* $NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg 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.9 2011/06/18 22:17:58 bsiegert Exp $";
+static char rcsid[] = "$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg 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.9 2011/06/18 22:17:58 bsiegert Exp $");
+__RCSID("$NetBSD: job.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
#endif
#endif /* not lint */
#endif
@@ -142,6 +142,7 @@ __RCSID("$NetBSD: job.c,v 1.1.1.9 2011/06/18 22:17:58 bsiegert Exp $");
#include <sys/time.h>
#include "wait.h"
+#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
@@ -312,6 +313,7 @@ static Shell *commandShell = &shells[DEFSHELL_INDEX]; /* this is the shell to
const char *shellPath = NULL, /* full pathname of
* executable image */
*shellName = NULL; /* last component of shell */
+char *shellErrFlag = NULL;
static const char *shellArgv = NULL; /* Custom shell args */
@@ -334,10 +336,7 @@ static int readyfd(Job *);
STATIC GNode *lastNode; /* The node for which output was most recently
* produced. */
-STATIC const char *targFmt; /* Format string to use to head output from a
- * job when it's not the most-recent job heard
- * from */
-static char *targPrefix = NULL; /* What we print at the start of targFmt */
+static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */
static Job tokenWaitJob; /* token wait pseudo-job */
static Job childExitJob; /* child exit pseudo-job */
@@ -346,7 +345,8 @@ static Job childExitJob; /* child exit pseudo-job */
#define TARG_FMT "%s %s ---\n" /* Default format */
#define MESSAGE(fp, gn) \
- (void)fprintf(fp, targFmt, targPrefix, gn->name)
+ 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)
@@ -367,7 +367,7 @@ static int JobStart(GNode *, int);
static char *JobOutput(Job *, char *, char *, int);
static void JobDoOutput(Job *, Boolean);
static Shell *JobMatchShell(const char *);
-static void JobInterrupt(int, int);
+static void JobInterrupt(int, int) MAKE_ATTR_DEAD;
static void JobRestartJobs(void);
static void JobTokenAdd(void);
static void JobSigLock(sigset_t *);
@@ -415,6 +415,15 @@ JobCreatePipe(Job *job, int minfd)
if (pipe(job->jobPipe) == -1)
Punt("Cannot create pipe: %s", strerror(errno));
+ for (i = 0; i < 2; i++) {
+ /* Avoid using low numbered fds */
+ fd = fcntl(job->jobPipe[i], F_DUPFD, minfd);
+ if (fd != -1) {
+ close(job->jobPipe[i]);
+ job->jobPipe[i] = fd;
+ }
+ }
+
/* Set close-on-exec flag for both */
(void)fcntl(job->jobPipe[0], F_SETFD, 1);
(void)fcntl(job->jobPipe[1], F_SETFD, 1);
@@ -427,15 +436,6 @@ JobCreatePipe(Job *job, int minfd)
*/
fcntl(job->jobPipe[0], F_SETFL,
fcntl(job->jobPipe[0], F_GETFL, 0) | O_NONBLOCK);
-
- for (i = 0; i < 2; i++) {
- /* Avoid using low numbered fds */
- fd = fcntl(job->jobPipe[i], F_DUPFD, minfd);
- if (fd != -1) {
- close(job->jobPipe[i]);
- job->jobPipe[i] = fd;
- }
- }
}
/*-
@@ -490,9 +490,10 @@ JobCondPassSig(int signo)
*-----------------------------------------------------------------------
*/
static void
-JobChildSig(int signo __unused)
+JobChildSig(int signo MAKE_ATTR_UNUSED)
{
- write(childExitJob.outPipe, CHILD_EXIT, 1);
+ while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN)
+ continue;
}
@@ -513,13 +514,15 @@ JobChildSig(int signo __unused)
*-----------------------------------------------------------------------
*/
static void
-JobContinueSig(int signo __unused)
+JobContinueSig(int signo MAKE_ATTR_UNUSED)
{
/*
* Defer sending to SIGCONT to our stopped children until we return
* from the signal handler.
*/
- write(childExitJob.outPipe, DO_JOB_RESUME, 1);
+ while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
+ errno == EAGAIN)
+ continue;
}
/*-
@@ -538,14 +541,14 @@ JobContinueSig(int signo __unused)
*
*-----------------------------------------------------------------------
*/
-static void
+MAKE_ATTR_DEAD static void
JobPassSig_int(int signo)
{
/* Run .INTERRUPT target then exit */
JobInterrupt(TRUE, signo);
}
-static void
+MAKE_ATTR_DEAD static void
JobPassSig_term(int signo)
{
/* Dont run .INTERRUPT target then exit */
@@ -690,7 +693,6 @@ JobPrintCommand(void *cmdp, void *jobp)
char *escCmd = NULL; /* Command with quotes/backticks escaped */
char *cmd = (char *)cmdp;
Job *job = (Job *)jobp;
- char *cp, *tmp;
int i, j;
noSpecials = NoExecute(job->node);
@@ -726,7 +728,6 @@ JobPrintCommand(void *cmdp, void *jobp)
shutUp = DEBUG(LOUD) ? FALSE : TRUE;
break;
case '-':
- job->flags |= JOB_IGNERR;
errOff = TRUE;
break;
case '+':
@@ -805,6 +806,7 @@ JobPrintCommand(void *cmdp, void *jobp)
* to ignore errors. Set cmdTemplate to use the weirdness
* instead of the simple "%s\n" template.
*/
+ job->flags |= JOB_IGNERR;
if (!(job->flags & JOB_SILENT) && !shutUp) {
if (commandShell->hasEchoCtl) {
DBPRINTF("%s\n", commandShell->echoOff);
@@ -862,11 +864,6 @@ JobPrintCommand(void *cmdp, void *jobp)
job->flags |= JOB_TRACED;
}
- if ((cp = Check_Cwd_Cmd(cmd)) != NULL) {
- DBPRINTF("test -d %s && ", cp);
- DBPRINTF("cd %s\n", cp);
- }
-
DBPRINTF(cmdTemplate, cmd);
free(cmdStart);
if (escCmd)
@@ -886,10 +883,6 @@ JobPrintCommand(void *cmdp, void *jobp)
if (shutUp && commandShell->hasEchoCtl) {
DBPRINTF("%s\n", commandShell->echoOn);
}
- if (cp != NULL) {
- DBPRINTF("test -d %s && ", cp);
- DBPRINTF("cd %s\n", Var_Value(".OBJDIR", VAR_GLOBAL, &tmp));
- }
return 0;
}
@@ -1149,7 +1142,8 @@ Job_Touch(GNode *gn, Boolean silent)
int streamID; /* ID of stream opened to do the touch */
struct utimbuf times; /* Times for utime() call */
- if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|OP_PHONY)) {
+ if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|
+ OP_SPECIAL|OP_PHONY)) {
/*
* .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
* and, as such, shouldn't really be created.
@@ -1186,7 +1180,8 @@ Job_Touch(GNode *gn, Boolean silent)
*/
if (read(streamID, &c, 1) == 1) {
(void)lseek(streamID, (off_t)0, SEEK_SET);
- (void)write(streamID, &c, 1);
+ while (write(streamID, &c, 1) == -1 && errno == EAGAIN)
+ continue;
}
(void)close(streamID);
@@ -1241,7 +1236,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn, 0);
if (p1)
free(p1);
- } else if (Dir_MTime(gn) == 0 && (gn->type & OP_SPECIAL) == 0) {
+ } 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
* rule to go on and the target doesn't already exist. There's
@@ -1252,8 +1247,10 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
static const char msg[] = ": don't know how to make";
if (gn->flags & FROM_DEPEND) {
- fprintf(stdout, "%s: ignoring stale %s for %s\n",
- progname, makeDependfile, gn->name);
+ if (!Job_RunTarget(".STALE", gn->fname))
+ fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n",
+ progname, gn->fname, gn->lineno, makeDependfile,
+ gn->name);
return TRUE;
}
@@ -1363,7 +1360,7 @@ JobExec(Job *job, char **argv)
(void)fcntl(0, F_SETFD, 0);
(void)lseek(0, (off_t)0, SEEK_SET);
- if (job->node->type & OP_MAKE) {
+ if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
/*
* Pass job token pipe to submakes.
*/
@@ -1396,11 +1393,15 @@ JobExec(Job *job, char **argv)
* we can kill it and all its descendants in one fell swoop,
* by killing its process family, but not commit suicide.
*/
-#if defined(SYSV)
+#if defined(HAVE_SETPGID)
+ (void)setpgid(0, getpid());
+#else
+#if defined(HAVE_SETSID)
/* XXX: dsl - I'm sure this should be setpgrp()... */
(void)setsid();
#else
- (void)setpgid(0, getpid());
+ (void)setpgrp(0, getpid());
+#endif
#endif
Var_ExportVars();
@@ -1607,6 +1608,9 @@ JobStart(GNode *gn, int flags)
#ifdef USE_META
if (useMeta) {
meta_job_start(job, gn);
+ if (Targ_Silent(gn)) { /* might have changed */
+ job->flags |= JOB_SILENT;
+ }
}
#endif
/*
@@ -1890,16 +1894,16 @@ end_loop:
(void)fflush(stdout);
}
}
- if (i < max - 1) {
- /* shift the remaining characters down */
- (void)memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
+ /*
+ * max is the last offset still in the buffer. Move any remaining
+ * characters to the start of the buffer and update the end marker
+ * curPos.
+ */
+ if (i < max) {
+ (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
job->curPos = max - (i + 1);
-
} else {
- /*
- * We have written everything out, so we just start over
- * from the start of the buffer. No copying. No nothing.
- */
+ assert(i == max);
job->curPos = 0;
}
}
@@ -2063,31 +2067,45 @@ Job_CatchOutput(void)
(void)fflush(stdout);
/* The first fd in the list is the job token pipe */
- nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC);
+ do {
+ nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC);
+ } while (nready < 0 && errno == EINTR);
- if (nready < 0 || readyfd(&childExitJob)) {
+ if (nready < 0)
+ Punt("poll: %s", strerror(errno));
+
+ if (nready > 0 && readyfd(&childExitJob)) {
char token = 0;
- nready -= 1;
- (void)read(childExitJob.inPipe, &token, 1);
- if (token == DO_JOB_RESUME[0])
- /* Complete relay requested from our SIGCONT handler */
- JobRestartJobs();
- Job_CatchChildren();
+ ssize_t count;
+ count = read(childExitJob.inPipe, &token, 1);
+ switch (count) {
+ case 0:
+ Punt("unexpected eof on token pipe");
+ case -1:
+ Punt("token pipe read: %s", strerror(errno));
+ case 1:
+ if (token == DO_JOB_RESUME[0])
+ /* Complete relay requested from our SIGCONT handler */
+ JobRestartJobs();
+ break;
+ default:
+ abort();
+ }
+ --nready;
}
- if (nready <= 0)
- return;
-
- if (wantToken && readyfd(&tokenWaitJob))
- nready--;
+ Job_CatchChildren();
+ if (nready == 0)
+ return;
for (i = 2; i < nfds; i++) {
if (!fds[i].revents)
continue;
job = jobfds[i];
- if (job->job_state != JOB_ST_RUNNING)
- continue;
- JobDoOutput(job, FALSE);
+ if (job->job_state == JOB_ST_RUNNING)
+ JobDoOutput(job, FALSE);
+ if (--nready == 0)
+ return;
}
}
@@ -2135,6 +2153,24 @@ Shell_Init(void)
if (commandShell->echo == NULL) {
commandShell->echo = "";
}
+ if (commandShell->hasErrCtl && *commandShell->exit) {
+ if (shellErrFlag &&
+ strcmp(commandShell->exit, &shellErrFlag[1]) != 0) {
+ free(shellErrFlag);
+ shellErrFlag = NULL;
+ }
+ if (!shellErrFlag) {
+ int n = strlen(commandShell->exit) + 2;
+
+ shellErrFlag = bmake_malloc(n);
+ if (shellErrFlag) {
+ snprintf(shellErrFlag, n, "-%s", commandShell->exit);
+ }
+ }
+ } else if (shellErrFlag) {
+ free(shellErrFlag);
+ shellErrFlag = NULL;
+ }
}
/*-
@@ -2178,8 +2214,7 @@ Job_SetPrefix(void)
void
Job_Init(void)
{
- GNode *begin; /* node for commands to do at the very start */
-
+ Job_SetPrefix();
/* Allocate space for all the job info */
job_table = bmake_malloc(maxJobs * sizeof *job_table);
memset(job_table, 0, maxJobs * sizeof *job_table);
@@ -2191,16 +2226,6 @@ Job_Init(void)
lastNode = NULL;
- if (maxJobs == 1) {
- /*
- * If only one job can run at a time, there's no need for a banner,
- * is there?
- */
- targFmt = "";
- } else {
- targFmt = TARG_FMT;
- }
-
/*
* There is a non-zero chance that we already have children.
* eg after 'make -f- <<EOF'
@@ -2265,15 +2290,7 @@ Job_Init(void)
ADDSIG(SIGCONT, JobContinueSig)
#undef ADDSIG
- begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);
-
- if (begin != NULL) {
- JobRun(begin);
- if (begin->made == ERROR) {
- PrintOnError(begin, "\n\nStop.");
- exit(1);
- }
- }
+ (void)Job_RunTarget(".BEGIN", NULL);
postCommands = Targ_FindNode(".END", TARG_CREATE);
}
@@ -2445,7 +2462,7 @@ Job_ParseShell(char *line)
* If no path was given, the user wants one of the pre-defined shells,
* yes? So we find the one s/he wants with the help of JobMatchShell
* and set things up the right way. shellPath will be set up by
- * Job_Init.
+ * Shell_Init.
*/
if (newShell.name == NULL) {
Parse_Error(PARSE_FATAL, "Neither path nor name specified");
@@ -2460,6 +2477,12 @@ Job_ParseShell(char *line)
}
commandShell = sh;
shellName = newShell.name;
+ if (shellPath) {
+ /* Shell_Init has already been called! Do it again. */
+ free(UNCONST(shellPath));
+ shellPath = NULL;
+ Shell_Init();
+ }
}
} else {
/*
@@ -2493,6 +2516,8 @@ Job_ParseShell(char *line)
commandShell = bmake_malloc(sizeof(Shell));
*commandShell = newShell;
}
+ /* this will take care of shellErrFlag */
+ Shell_Init();
}
if (commandShell->echoOn && commandShell->echoOff) {
@@ -2803,7 +2828,8 @@ JobTokenAdd(void)
if (DEBUG(JOB))
fprintf(debug_file, "(%d) aborting %d, deposit token %c\n",
getpid(), aborting, JOB_TOKENS[aborting]);
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
}
/*-
@@ -2824,6 +2850,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);
return;
}
@@ -2916,13 +2944,15 @@ Job_TokenWithdraw(void)
while (read(tokenWaitJob.inPipe, &tok1, 1) == 1)
continue;
/* And put the stopper back */
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
Fatal("A failure has been detected in another branch of the parallel make");
}
if (count == 1 && jobTokensRunning == 0)
/* We didn't want the token really */
- write(tokenWaitJob.outPipe, &tok, 1);
+ while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
+ continue;
jobTokensRunning++;
if (DEBUG(JOB))
@@ -2930,6 +2960,38 @@ Job_TokenWithdraw(void)
return TRUE;
}
+/*-
+ *-----------------------------------------------------------------------
+ * Job_RunTarget --
+ * Run the named target if found. If a filename is specified, then
+ * set that to the sources.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * exits if the target fails.
+ *
+ *-----------------------------------------------------------------------
+ */
+Boolean
+Job_RunTarget(const char *target, const char *fname) {
+ GNode *gn = Targ_FindNode(target, TARG_NOCREATE);
+
+ if (gn == NULL)
+ return FALSE;
+
+ if (fname)
+ Var_Set(ALLSRC, fname, gn, 0);
+
+ JobRun(gn);
+ if (gn->made == ERROR) {
+ PrintOnError(gn, "\n\nStop.");
+ exit(1);
+ }
+ return TRUE;
+}
+
#ifdef USE_SELECT
int
emul_poll(struct pollfd *fd, int nfd, int timeout)