[klibc] [klibc:update-dash] eval: Reap zombies after built-in commands and functions

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


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

[klibc] eval: Reap zombies after built-in commands and functions

Currently dash does not reap dead children after built-in commands
or functions.  This means that if you construct a loop consisting
of solely built-in commands and functions, then zombies can hang
around indefinitely.

This patch fixes this by reaping when necessary after each built-in
command and function.

Reported-by: Denys Vlasenko <vda.linux at googlemail.com>
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 | 11 ++++++-----
 usr/dash/jobs.c |  8 +++++---
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/usr/dash/eval.c b/usr/dash/eval.c
index 6ba64b12..811c28a4 100644
--- a/usr/dash/eval.c
+++ b/usr/dash/eval.c
@@ -848,6 +848,8 @@ bail:
 		goto out;
 	}
 
+	jp = NULL;
+
 	/* Execute the command. */
 	switch (cmdentry.cmdtype) {
 	default:
@@ -856,7 +858,6 @@ bail:
 			INTOFF;
 			jp = makejob(cmd, 1);
 			if (forkshell(jp, cmd, FORK_FG) != 0) {
-				status = waitforjob(jp);
 				INTON;
 				break;
 			}
@@ -875,22 +876,22 @@ bail:
 		if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
 			if (exception == EXERROR && spclbltin <= 0) {
 				FORCEINTON;
-				goto readstatus;
+				break;
 			}
 raise:
 			longjmp(handler->loc, 1);
 		}
-		goto readstatus;
+		break;
 
 	case CMDFUNCTION:
 		poplocalvars(1);
 		if (evalfun(cmdentry.u.func, argc, argv, flags))
 			goto raise;
-readstatus:
-		status = exitstatus;
 		break;
 	}
 
+	status = waitforjob(jp);
+
 out:
 	if (cmd->ncmd.redirect)
 		popredir(execcmd);
diff --git a/usr/dash/jobs.c b/usr/dash/jobs.c
index a2602bae..4548ae69 100644
--- a/usr/dash/jobs.c
+++ b/usr/dash/jobs.c
@@ -53,6 +53,7 @@
 #include <termios.h>
 #undef CEOF			/* syntax.h redefines this */
 #endif
+#include "eval.h"
 #include "redir.h"
 #include "show.h"
 #include "main.h"
@@ -972,10 +973,11 @@ waitforjob(struct job *jp)
 {
 	int st;
 
-	TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
-	while (jp->state == JOBRUNNING) {
+	TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
+	while ((jp && jp->state == JOBRUNNING) || gotsigchld)
 		dowait(DOWAIT_BLOCK, jp);
-	}
+	if (!jp)
+		return exitstatus;
 	st = getstatus(jp);
 #if JOBS
 	if (jp->jobctl) {


More information about the klibc mailing list