aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-02-18 14:37:56 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2020-02-18 15:37:22 +0100
commit97edfc42f112a15828aaec886ef7012d24f34d5e (patch)
tree49297967a0a7a1e1288e2113edc18d1fcbf813d8
parentd81af7216b3305a1aac211dc847dd1c191f3b307 (diff)
downloadbusybox-w32-97edfc42f112a15828aaec886ef7012d24f34d5e.tar.gz
busybox-w32-97edfc42f112a15828aaec886ef7012d24f34d5e.tar.bz2
busybox-w32-97edfc42f112a15828aaec886ef7012d24f34d5e.zip
ash: jobs - Do not block when waiting on SIGCHLD
Upstream comment: Date: Mon, 7 May 2018 00:40:34 +0800 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@gondor.apana.org.au> While at it, removed INT_ON/OFF in waitforjob() - it must be called from INT_OFF region anyway. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 8047cf98f..2b1378694 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5357,8 +5357,16 @@ waitforjob(struct job *jp)
5357 5357
5358 TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0)); 5358 TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
5359 5359
5360 INT_OFF; 5360 if (!jp) {
5361 while ((jp && jp->state == JOBRUNNING) || got_sigchld) { 5361 int pid = got_sigchld;
5362
5363 while (pid > 0)
5364 pid = dowait(DOWAIT_NONBLOCK, NULL);
5365
5366 return exitstatus;
5367 }
5368
5369 while (jp->state == JOBRUNNING) {
5362 /* In non-interactive shells, we _can_ get 5370 /* In non-interactive shells, we _can_ get
5363 * a keyboard signal here and be EINTRed, 5371 * a keyboard signal here and be EINTRed,
5364 * but we just loop back, waiting for command to complete. 5372 * but we just loop back, waiting for command to complete.
@@ -5391,10 +5399,7 @@ waitforjob(struct job *jp)
5391 */ 5399 */
5392 dowait(DOWAIT_BLOCK, jp); 5400 dowait(DOWAIT_BLOCK, jp);
5393 } 5401 }
5394 INT_ON;
5395 5402
5396 if (!jp)
5397 return exitstatus;
5398 st = getstatus(jp); 5403 st = getstatus(jp);
5399#if JOBS 5404#if JOBS
5400 if (jp->jobctl) { 5405 if (jp->jobctl) {
@@ -10369,7 +10374,6 @@ evalcommand(union node *cmd, int flags)
10369 jp = makejob(/*cmd,*/ 1); 10374 jp = makejob(/*cmd,*/ 1);
10370 if (forkshell(jp, cmd, FORK_FG) != 0) { 10375 if (forkshell(jp, cmd, FORK_FG) != 0) {
10371 /* parent */ 10376 /* parent */
10372 INT_ON;
10373 TRACE(("forked child exited with %d\n", status)); 10377 TRACE(("forked child exited with %d\n", status));
10374 break; 10378 break;
10375 } 10379 }
@@ -10387,11 +10391,9 @@ evalcommand(union node *cmd, int flags)
10387 if (cmd_is_exec && argc > 1) 10391 if (cmd_is_exec && argc > 1)
10388 listsetvar(varlist.list, VEXPORT); 10392 listsetvar(varlist.list, VEXPORT);
10389 } 10393 }
10390 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { 10394 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
10391 if (exception_type == EXERROR && spclbltin <= 0) { 10395 && !(exception_type == EXERROR && spclbltin <= 0)
10392 FORCE_INT_ON; 10396 ) {
10393 break;
10394 }
10395 raise: 10397 raise:
10396 longjmp(exception_handler->loc, 1); 10398 longjmp(exception_handler->loc, 1);
10397 } 10399 }
@@ -10404,6 +10406,7 @@ evalcommand(union node *cmd, int flags)
10404 } /* switch */ 10406 } /* switch */
10405 10407
10406 status = waitforjob(jp); 10408 status = waitforjob(jp);
10409 FORCE_INT_ON;
10407 10410
10408 out: 10411 out:
10409 if (cmd->ncmd.redirect) 10412 if (cmd->ncmd.redirect)