aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2018-05-07 00:40:34 +0800
committerBen Hutchings <ben@decadent.org.uk>2020-03-28 21:42:55 +0000
commitdfe960aa216a4495cf926fac099caacabc5684e3 (patch)
tree11f8f151cec13b0e82d050cc1b4b267b9289cd97
parent4f8448353f3b894eac522461109df97ea6af6a54 (diff)
downloadklibc-dfe960aa216a4495cf926fac099caacabc5684e3.tar.gz
[klibc] dash: jobs - Do not block when waiting on SIGCHLD
[ dash commit 9e5cd41d9605e4caaac3aacdc0482f6ee220a298 ] Because of the nature of SIGCHLD, the process may have already been waited on and therefore we must be prepared for the case that wait may block. So ensure that it doesn't by using WNOHANG. Furthermore, multiple jobs may have exited when gotsigchld is set. Therefore we need to wait until there are no zombies left. Lastly, waitforjob needs to be called with interrupts off and the original patch broke that. Fixes: 03876c0743a5 ("eval: Reap zombies after built-in...") Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rw-r--r--usr/dash/eval.c12
-rw-r--r--usr/dash/jobs.c13
2 files changed, 14 insertions, 11 deletions
diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 722066e5d6857..13e690e74765f 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -859,10 +859,8 @@ bail:
if (!(flags & EV_EXIT) || have_traps()) {
INTOFF;
jp = makejob(cmd, 1);
- if (forkshell(jp, cmd, FORK_FG) != 0) {
- INTON;
+ if (forkshell(jp, cmd, FORK_FG) != 0)
break;
- }
FORCEINTON;
}
listsetvar(varlist.list, VEXPORT|VSTACK);
@@ -875,11 +873,8 @@ bail:
if (execcmd && argc > 1)
listsetvar(varlist.list, VEXPORT);
}
- if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
- if (exception == EXERROR && spclbltin <= 0) {
- FORCEINTON;
- break;
- }
+ if (evalbltin(cmdentry.u.cmd, argc, argv, flags) &&
+ !(exception == EXERROR && spclbltin <= 0)) {
raise:
longjmp(handler->loc, 1);
}
@@ -892,6 +887,7 @@ raise:
}
status = waitforjob(jp);
+ FORCEINTON;
out:
if (cmd->ncmd.redirect)
diff --git a/usr/dash/jobs.c b/usr/dash/jobs.c
index 3ea7e12226506..400628ff98101 100644
--- a/usr/dash/jobs.c
+++ b/usr/dash/jobs.c
@@ -974,10 +974,17 @@ waitforjob(struct job *jp)
int st;
TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
- while ((jp && jp->state == JOBRUNNING) || gotsigchld)
- dowait(DOWAIT_BLOCK, jp);
- if (!jp)
+ if (!jp) {
+ int pid = gotsigchld;
+
+ while (pid > 0)
+ pid = dowait(DOWAIT_NORMAL, NULL);
+
return exitstatus;
+ }
+
+ while (jp->state == JOBRUNNING)
+ dowait(DOWAIT_BLOCK, jp);
st = getstatus(jp);
#if JOBS
if (jp->jobctl) {