[klibc] [klibc:update-dash] jobs - Do not block when waiting on SIGCHLD

klibc-bot for Herbert Xu herbert at gondor.apana.org.au
Thu Jan 24 19:16:01 PST 2019


Commit-ID:  de74268fc82f0b99743904f5d18a69ad690eec2c
Gitweb:     http://git.kernel.org/?p=libs/klibc/klibc.git;a=commit;h=de74268fc82f0b99743904f5d18a69ad690eec2c
Author:     Herbert Xu <herbert at gondor.apana.org.au>
AuthorDate: Mon, 7 May 2018 00:40:34 +0800
Committer:  Ben Hutchings <ben at decadent.org.uk>
CommitDate: Fri, 25 Jan 2019 02:57:21 +0000

[klibc] jobs - Do not block when waiting on SIGCHLD

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 at gondor.apana.org.au>
Signed-off-by: Ben Hutchings <ben at decadent.org.uk>

---
 usr/dash/eval.c | 12 ++++--------
 usr/dash/jobs.c | 13 ++++++++++---
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 2f662e3e..56661880 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 4548ae69..2b8e1afe 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) {


More information about the klibc mailing list