aboutsummaryrefslogtreecommitdiff
path: root/contrib/bmake/job.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bmake/job.c')
-rw-r--r--contrib/bmake/job.c191
1 files changed, 72 insertions, 119 deletions
diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c
index 8cfe116dffd8..4cce19e89f87 100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.452 2022/02/12 11:14:48 rillig Exp $ */
+/* $NetBSD: job.c,v 1.467 2024/03/10 02:53:37 sjg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,12 +70,11 @@
*/
/*
- * job.c --
- * handle the creation etc. of our child processes.
+ * Create child processes and collect their output.
*
* Interface:
* Job_Init Called to initialize this module. In addition,
- * the .BEGIN target is made including all of its
+ * the .BEGIN target is made, including all of its
* dependencies before this function returns.
* Hence, the makefiles must have been parsed
* before this function is called.
@@ -155,7 +154,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.452 2022/02/12 11:14:48 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.467 2024/03/10 02:53:37 sjg Exp $");
/*
* A shell defines how the commands are run. All commands for a target are
@@ -274,9 +273,7 @@ static bool Always_pass_job_queue = true;
#define MAKE_JOB_ERROR_TOKEN "${MAKE_JOB_ERROR_TOKEN:U}"
static bool Job_error_token = true;
-/*
- * error handling variables
- */
+/* error handling variables */
static int job_errors = 0; /* number of errors reported */
static enum { /* Why is the make aborting? */
ABORT_NONE,
@@ -286,9 +283,7 @@ static enum { /* Why is the make aborting? */
} aborting = ABORT_NONE;
#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
-/*
- * this tracks the number of tokens currently "out" to build jobs.
- */
+/* Tracks the number of tokens currently "out" to build jobs. */
int jobTokensRunning = 0;
typedef enum JobStartResult {
@@ -317,15 +312,15 @@ typedef enum JobStartResult {
#define DEFSHELL_INDEX_SH 1
#define DEFSHELL_INDEX_KSH 2
#define DEFSHELL_INDEX_CSH 3
-#else /* !DEFSHELL_CUSTOM */
+#else
#define DEFSHELL_INDEX_SH 0
#define DEFSHELL_INDEX_KSH 1
#define DEFSHELL_INDEX_CSH 2
-#endif /* !DEFSHELL_CUSTOM */
+#endif
#ifndef DEFSHELL_INDEX
#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
-#endif /* !DEFSHELL_INDEX */
+#endif
static Shell shells[] = {
#ifdef DEFSHELL_CUSTOM
@@ -441,7 +436,7 @@ static char *shell_freeIt = NULL; /* Allocated memory for custom .SHELL */
static Job *job_table; /* The structures that describe them */
static Job *job_table_end; /* job_table + maxJobs */
-static unsigned int wantToken; /* we want a token */
+static unsigned int wantToken;
static bool lurking_children = false;
static bool make_suspended = false; /* Whether we've seen a SIGTSTP (etc) */
@@ -541,7 +536,7 @@ JobDeleteTarget(GNode *gn)
return;
file = GNode_Path(gn);
- if (unlink_file(file))
+ if (unlink_file(file) == 0)
Error("*** %s removed", file);
}
@@ -576,7 +571,7 @@ JobCreatePipe(Job *job, int minfd)
Punt("Cannot create pipe: %s", strerror(errno));
for (i = 0; i < 2; i++) {
- /* Avoid using low numbered fds */
+ /* Avoid using low-numbered fds */
fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
if (fd != -1) {
close(pipe_fds[i]);
@@ -587,7 +582,6 @@ JobCreatePipe(Job *job, int minfd)
job->inPipe = pipe_fds[0];
job->outPipe = pipe_fds[1];
- /* Set close-on-exec flag for both */
if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
Punt("Cannot set close-on-exec: %s", strerror(errno));
if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
@@ -710,10 +704,10 @@ JobPassSig_suspend(int signo)
/*
* We've been continued.
*
- * A whole host of signals continue to happen!
+ * A whole host of signals is going to happen!
* SIGCHLD for any processes that actually suspended themselves.
- * SIGCHLD for any processes that exited while we were alseep.
- * The SIGCONT that actually caused us to wakeup.
+ * SIGCHLD for any processes that exited while we were asleep.
+ * The SIGCONT that actually caused us to wake up.
*
* Since we defer passing the SIGCONT on to our children until
* the main processing loop, we can be sure that all the SIGCHLD
@@ -761,7 +755,8 @@ ParseCommandFlags(char **pp, CommandFlags *out_cmdFlags)
out_cmdFlags->ignerr = true;
else if (*p == '+')
out_cmdFlags->always = true;
- else
+ else if (!ch_isspace(*p))
+ /* Ignore whitespace for compatibility with GNU make */
break;
p++;
}
@@ -891,13 +886,9 @@ static void
JobWriteSpecials(Job *job, ShellWriter *wr, const char *escCmd, bool run,
CommandFlags *inout_cmdFlags, const char **inout_cmdTemplate)
{
- if (!run) {
- /*
- * If there is no command to run, there is no need to switch
- * error checking off and on again for nothing.
- */
+ if (!run)
inout_cmdFlags->ignerr = false;
- } else if (shell->hasErrCtl)
+ else if (shell->hasErrCtl)
ShellWriter_ErrOff(wr, job->echo && inout_cmdFlags->echo);
else if (shell->runIgnTmpl != NULL && shell->runIgnTmpl[0] != '\0') {
JobWriteSpecialsEchoCtl(job, wr, inout_cmdFlags, escCmd,
@@ -939,7 +930,7 @@ JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd)
run = GNode_ShouldExecute(job->node);
- (void)Var_Subst(ucmd, job->node, VARE_WANTRES, &xcmd);
+ xcmd = Var_Subst(ucmd, job->node, VARE_WANTRES);
/* TODO: handle errors */
xcmdStart = xcmd;
@@ -966,12 +957,10 @@ JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd)
escCmd = shell->hasErrCtl ? NULL : EscapeShellDblQuot(xcmd);
if (!cmdFlags.echo) {
- if (job->echo && run && shell->hasEchoCtl) {
+ if (job->echo && run && shell->hasEchoCtl)
ShellWriter_EchoOff(wr);
- } else {
- if (shell->hasErrCtl)
- cmdFlags.echo = true;
- }
+ else if (shell->hasErrCtl)
+ cmdFlags.echo = true;
}
if (cmdFlags.ignerr) {
@@ -1068,7 +1057,7 @@ JobSaveCommands(Job *job)
* variables such as .TARGET, .IMPSRC. It is not intended to
* expand the other variables as well; see deptgt-end.mk.
*/
- (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
+ expanded_cmd = Var_Subst(cmd, job->node, VARE_WANTRES);
/* TODO: handle errors */
Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
}
@@ -1104,8 +1093,7 @@ DebugFailedJob(const Job *job)
debug_printf("\t%s\n", cmd);
if (strchr(cmd, '$') != NULL) {
- char *xcmd;
- (void)Var_Subst(cmd, job->node, VARE_WANTRES, &xcmd);
+ char *xcmd = Var_Subst(cmd, job->node, VARE_WANTRES);
debug_printf("\t=> %s\n", xcmd);
free(xcmd);
}
@@ -1420,7 +1408,7 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
return false;
}
- abortProc("%s: don't know how to make %s. Stop", progname, gn->name);
+ abortProc("don't know how to make %s. Stop", gn->name);
return false;
}
@@ -1447,7 +1435,7 @@ JobExec(Job *job, char **argv)
}
/*
- * Some jobs produce no output and it's disconcerting to have
+ * Some jobs produce no output, and it's disconcerting to have
* no feedback of their running (since they produce no output, the
* banner with their name in it never appears). This is an attempt to
* provide that feedback, even if nothing follows it.
@@ -1461,7 +1449,7 @@ JobExec(Job *job, char **argv)
/* Pre-emptively mark job running, pid still zero though */
job->status = JOB_ST_RUNNING;
- Var_ReexportVars();
+ Var_ReexportVars(job->node);
cpid = vfork();
if (cpid == -1)
@@ -1500,9 +1488,7 @@ JobExec(Job *job, char **argv)
if (Always_pass_job_queue ||
(job->node->type & (OP_MAKE | OP_SUBMAKE))) {
- /*
- * Pass job token pipe to submakes.
- */
+ /* Pass job token pipe to submakes. */
if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1)
execDie("clear close-on-exec",
"tokenWaitJob.inPipe");
@@ -1798,12 +1784,12 @@ JobStart(GNode *gn, bool special)
* itself.
*/
static char *
-PrintFilteredOutput(char *cp, char *endp) /* XXX: should all be const */
+PrintFilteredOutput(char *p, char *endp) /* XXX: should all be const */
{
- char *ecp; /* XXX: should be const */
+ char *ep; /* XXX: should be const */
if (shell->noPrint == NULL || shell->noPrint[0] == '\0')
- return cp;
+ return p;
/*
* XXX: What happens if shell->noPrint occurs on the boundary of
@@ -1811,9 +1797,9 @@ PrintFilteredOutput(char *cp, char *endp) /* XXX: should all be const */
* be a proper stream filter instead of doing string matching on
* selected chunks of the output.
*/
- while ((ecp = strstr(cp, shell->noPrint)) != NULL) {
- if (ecp != cp) {
- *ecp = '\0'; /* XXX: avoid writing to the buffer */
+ while ((ep = strstr(p, shell->noPrint)) != NULL) {
+ if (ep != p) {
+ *ep = '\0'; /* XXX: avoid writing to the buffer */
/*
* The only way there wouldn't be a newline after
* this line is if it were the last in the buffer.
@@ -1821,16 +1807,16 @@ PrintFilteredOutput(char *cp, char *endp) /* XXX: should all be const */
* there must be a newline, so we don't print one.
*/
/* XXX: What about null bytes in the output? */
- (void)fprintf(stdout, "%s", cp);
+ (void)fprintf(stdout, "%s", p);
(void)fflush(stdout);
}
- cp = ecp + shell->noPrintLen;
- if (cp == endp)
+ p = ep + shell->noPrintLen;
+ if (p == endp)
break;
- cp++; /* skip over the (XXX: assumed) newline */
- pp_skip_whitespace(&cp);
+ p++; /* skip over the (XXX: assumed) newline */
+ pp_skip_whitespace(&p);
}
- return cp;
+ return p;
}
/*
@@ -1868,46 +1854,36 @@ again:
if (nRead < 0) {
if (errno == EAGAIN)
return;
- if (DEBUG(JOB)) {
+ if (DEBUG(JOB))
perror("CollectOutput(piperead)");
- }
nr = 0;
- } else {
+ } else
nr = (size_t)nRead;
- }
+
+ if (nr == 0)
+ finish = false; /* stop looping */
/*
* If we hit the end-of-file (the job is dead), we must flush its
* remaining output, so pretend we read a newline if there's any
* output remaining in the buffer.
- * Also clear the 'finish' flag so we stop looping.
*/
if (nr == 0 && job->curPos != 0) {
job->outBuf[job->curPos] = '\n';
nr = 1;
- finish = false;
- } else if (nr == 0) {
- finish = false;
}
- /*
- * Look for the last newline in the bytes we just got. If there is
- * one, break out of the loop with 'i' as its index and gotNL set
- * true.
- */
max = job->curPos + nr;
+ for (i = job->curPos; i < max; i++)
+ if (job->outBuf[i] == '\0')
+ job->outBuf[i] = ' ';
+
+ /* Look for the last newline in the bytes we just got. */
for (i = job->curPos + nr - 1;
i >= job->curPos && i != (size_t)-1; i--) {
if (job->outBuf[i] == '\n') {
gotNL = true;
break;
- } else if (job->outBuf[i] == '\0') {
- /*
- * FIXME: The null characters are only replaced with
- * space _after_ the last '\n'. Everywhere else they
- * hide the rest of the command output.
- */
- job->outBuf[i] = ' ';
}
}
@@ -1935,7 +1911,7 @@ again:
*/
job->outBuf[i] = '\0';
if (i >= job->curPos) {
- char *cp;
+ char *p;
/*
* FIXME: SwitchOutputTo should be here, according to
@@ -1943,23 +1919,23 @@ again:
* do anything in the default shell, this bug has gone
* unnoticed until now.
*/
- cp = PrintFilteredOutput(job->outBuf, &job->outBuf[i]);
+ p = PrintFilteredOutput(job->outBuf, &job->outBuf[i]);
/*
* There's still more in the output buffer. This time,
* though, we know there's no newline at the end, so
* we add one of our own free will.
*/
- if (*cp != '\0') {
+ if (*p != '\0') {
if (!opts.silent)
SwitchOutputTo(job->node);
#ifdef USE_META
if (useMeta) {
- meta_job_output(job, cp,
+ meta_job_output(job, p,
gotNL ? "\n" : "");
}
#endif
- (void)fprintf(stdout, "%s%s", cp,
+ (void)fprintf(stdout, "%s%s", p,
gotNL ? "\n" : "");
(void)fflush(stdout);
}
@@ -2100,6 +2076,8 @@ JobReapChild(pid_t pid, WAIT_T status, bool isJobs)
job->status = JOB_ST_FINISHED;
job->exit_status = WAIT_STATUS(status);
+ if (WIFEXITED(status))
+ job->node->exit_status = WEXITSTATUS(status);
JobFinish(job, status);
}
@@ -2239,14 +2217,13 @@ Shell_GetNewline(void)
void
Job_SetPrefix(void)
{
- if (targPrefix != NULL) {
+ if (targPrefix != NULL)
free(targPrefix);
- } else if (!Var_Exists(SCOPE_GLOBAL, MAKE_JOB_PREFIX)) {
- Global_Set(MAKE_JOB_PREFIX, "---");
- }
+ else if (!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOB.PREFIX"))
+ Global_Set(".MAKE.JOB.PREFIX", "---");
- (void)Var_Subst("${" MAKE_JOB_PREFIX "}",
- SCOPE_GLOBAL, VARE_WANTRES, &targPrefix);
+ targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}",
+ SCOPE_GLOBAL, VARE_WANTRES);
/* TODO: handle errors */
}
@@ -2316,9 +2293,7 @@ Job_Init(void)
watchfd(&childExitJob);
sigemptyset(&caught_signals);
- /*
- * Install a SIGCHLD handler.
- */
+ /* Install a SIGCHLD handler. */
(void)bmake_signal(SIGCHLD, JobChildSig);
sigaddset(&caught_signals, SIGCHLD);
@@ -2346,7 +2321,7 @@ Job_Init(void)
(void)Job_RunTarget(".BEGIN", NULL);
/*
* Create the .END node now, even though no code in the unit tests
- * depends on it. See also Targ_GetEndNode in Compat_Run.
+ * depends on it. See also Targ_GetEndNode in Compat_MakeAll.
*/
(void)Targ_GetEndNode();
}
@@ -2449,9 +2424,7 @@ Job_ParseShell(char *line)
memset(&newShell, 0, sizeof newShell);
- /*
- * Parse the specification by keyword
- */
+ /* Parse the specification by keyword. */
wordsList = Str_Words(line, true);
words = wordsList.words;
argc = wordsList.len;
@@ -2546,25 +2519,9 @@ Job_ParseShell(char *line)
}
}
} else {
- /*
- * The user provided a path. If s/he gave nothing else
- * (fullSpec is false), try and find a matching shell in the
- * ones we know of. Else we just take the specification at
- * its word and copy it to a new location. In either case,
- * we need to record the path the user gave for the shell.
- */
shellPath = path;
- path = strrchr(path, '/');
- if (path == NULL) {
- path = UNCONST(shellPath);
- } else {
- path++;
- }
- if (newShell.name != NULL) {
- shellName = newShell.name;
- } else {
- shellName = path;
- }
+ shellName = newShell.name != NULL ? newShell.name
+ : str_basename(path);
if (!fullSpec) {
if ((sh = FindShellByName(shellName)) == NULL) {
Parse_Error(PARSE_WARNING,
@@ -2661,11 +2618,10 @@ Job_Finish(void)
GNode *endNode = Targ_GetEndNode();
if (!Lst_IsEmpty(&endNode->commands) ||
!Lst_IsEmpty(&endNode->children)) {
- if (job_errors != 0) {
+ if (job_errors != 0)
Error("Errors reported so .END ignored");
- } else {
+ else
JobRun(endNode);
- }
}
return job_errors;
}
@@ -2805,9 +2761,7 @@ clearfd(Job *job)
fdsLen--;
}
#endif
- /*
- * Move last job in table into hole made by dead job.
- */
+ /* Move last job in table into hole made by dead job. */
if (fdsLen != i) {
fds[i] = fds[fdsLen];
jobByFdIndex[i] = jobByFdIndex[fdsLen];
@@ -2944,9 +2898,8 @@ Job_TokenWithdraw(void)
if (count == 0)
Fatal("eof on job pipe!");
if (count < 0 && jobTokensRunning != 0) {
- if (errno != EAGAIN) {
+ if (errno != EAGAIN)
Fatal("job pipe read: %s", strerror(errno));
- }
DEBUG1(JOB, "(%d) blocked for token\n", getpid());
wantToken = 1;
return false;