aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2020-09-29 16:44:46 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-01-01 14:30:58 +0100
commite4c7cf3f8cc67bd2b9aeb4d622c38bad515b09a0 (patch)
treea22a69c545bbc3e525e77c4e2b187ff2600ba9a9
parent4ac4f60942db83cb692fc94be28383f9c15a7379 (diff)
downloadbusybox-w32-e4c7cf3f8cc67bd2b9aeb4d622c38bad515b09a0.tar.gz
busybox-w32-e4c7cf3f8cc67bd2b9aeb4d622c38bad515b09a0.tar.bz2
busybox-w32-e4c7cf3f8cc67bd2b9aeb4d622c38bad515b09a0.zip
ash: jobs: Fix infinite loop in waitproc
Upstream commit: Date: Fri, 10 Apr 2020 21:03:09 +1000 jobs: Fix infinite loop in waitproc After we changed the resetting of gotsigchld so that it is only done if jp is NULL, we can now get an infinite loop in waitproc if gotsigchld is set but there is no outstanding child because everything had been waited for previously without gotsigchld being zeroed. This patch fixes it by always zeroing gotsigchld as we did before. The bug that the previous patch was trying to fix is now resolved by switching the blocking mode to DOWAIT_NORMAL after the specified job has been completed so that we really do wait for all outstanding dead children. Reported-by: Harald van Dijk <harald@gigawatt.nl> Fixes: 6c691b3e5099 ("jobs: Only clear gotsigchld when waiting...") Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> function old new delta dowait 553 631 +78 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c
index ac25866ec..13470b2fa 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -4453,15 +4453,28 @@ waitone(int block, struct job *job)
4453static int 4453static int
4454dowait(int block, struct job *jp) 4454dowait(int block, struct job *jp)
4455{ 4455{
4456 int pid = block == DOWAIT_NONBLOCK ? got_sigchld : 1; 4456 smallint gotchld = *(volatile smallint *)&got_sigchld;
4457 int rpid;
4458 int pid;
4459
4460 if (jp && jp->state != JOBRUNNING)
4461 block = DOWAIT_NONBLOCK;
4462
4463 if (block == DOWAIT_NONBLOCK && !gotchld)
4464 return 1;
4465
4466 rpid = 1;
4457 4467
4458 while (jp ? jp->state == JOBRUNNING : pid > 0) { 4468 do {
4459 if (!jp) 4469 got_sigchld = 0;
4460 got_sigchld = 0;
4461 pid = waitone(block, jp); 4470 pid = waitone(block, jp);
4462 } 4471 rpid &= !!pid;
4463 4472
4464 return pid; 4473 if (!pid || (jp && jp->state != JOBRUNNING))
4474 block = DOWAIT_NONBLOCK;
4475 } while (pid >= 0);
4476
4477 return rpid;
4465} 4478}
4466 4479
4467#if JOBS 4480#if JOBS