From: Dominique Martinet <[email protected]> wait -n would only return 127 if there is no job, not if there is no job not accounted for.
quick test: sh -c 'false & true & wait -n; echo $?; wait -n; echo $?; wait -n; echo $?' should print 1 0 127 This comes at a small size increase: function old new delta waitcmd 340 413 +73 waitone 449 399 -50 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 73/-50) Total: 23 bytes Tested-by: Wolfgang Zekoll <[email protected]> Signed-off-by: Dominique Martinet <[email protected]> --- v1 -> v2: - test wording v2 -> v3: - updated bloatcheck, which changed because of the extra '&& jp' check in waitcmd. In theory it shouldn't be needed unless something unsets pending_sig in a signal handler and I don't think it's ever done, but it's probably better safe than sorry here.. That means the two patches combined come with a +7 bytes cost. shell/ash.c | 48 ++++++++++++++++------------- shell/ash_test/ash-misc/wait8.right | 2 ++ shell/ash_test/ash-misc/wait8.tests | 14 +++++++++ 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index ee2d5c47c8b4..8abf3ca72cd4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4463,7 +4463,7 @@ waitproc(int block, int *status) return err; } -static int waitone(int block, struct job *job) +static struct job *waitone(int block, struct job *job) { int pid; int status; @@ -4494,7 +4494,7 @@ static int waitone(int block, struct job *job) pid = waitproc(block, &status); TRACE(("wait returns pid %d, status=%d\n", pid, status)); if (pid <= 0) - return pid; + return NULL; for (jp = curjob; jp; jp = jp->prev_job) { int jobstate; @@ -4559,35 +4559,31 @@ static int waitone(int block, struct job *job) } } - status = INT_MAX; - if (thisjob && thisjob->state == JOBDONE) - status = thisjob->ps[thisjob->nprocs - 1].ps_status; - - return status; + return thisjob; } -static int dowait_status(void) +static struct job *dowait_status(void) { - int status, rstatus = -ENOENT; + struct job *jp, *rjp = NULL; int block = DOWAIT_CHILD_OR_SIG; do { - status = waitone(block, NULL); - if (status >= 0 && status < INT_MAX) { - rstatus = status; + jp = waitone(block, NULL); + if (jp && jp->state == JOBDONE) { + rjp = jp; block = DOWAIT_NONBLOCK; } if (pending_sig) break; - } while (status >= 0); + } while (jp || !rjp); - return rstatus; + return rjp; } static void dowait(int block, struct job *jp) { smallint gotchld = *(volatile smallint *)&gotsigchld; - int status; + struct job *rjp; if (jp && jp->state != JOBRUNNING) block = DOWAIT_NONBLOCK; @@ -4596,11 +4592,11 @@ static void dowait(int block, struct job *jp) return; do { - status = waitone(block, jp); + rjp = waitone(block, jp); - if (!status || (jp && jp->state != JOBRUNNING)) + if (!rjp || (jp && jp->state != JOBRUNNING)) block = DOWAIT_NONBLOCK; - } while (status >= 0); + } while (block != DOWAIT_NONBLOCK || rjp); } #if JOBS @@ -4782,12 +4778,17 @@ waitcmd(int argc UNUSED_PARAM, char **argv) if (!argv[0]) { /* wait for all jobs / one job if -n */ for (;;) { - jp = curjob; #if BASH_WAIT_N - if (one && !jp) + if (one) { + for (jp = curjob; jp; jp = jp->prev_job) { + if (jp->state == JOBDONE && !jp->waited) + goto oneout; + } /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */ retval = 127; + } #endif + jp = curjob; while (1) { if (!jp) /* no running procs */ goto ret; @@ -4804,7 +4805,7 @@ waitcmd(int argc UNUSED_PARAM, char **argv) * the trap is executed." */ #if BASH_WAIT_N - status = dowait_status(); + jp = dowait_status(); #else dowait(DOWAIT_CHILD_OR_SIG, NULL); #endif @@ -4815,11 +4816,14 @@ waitcmd(int argc UNUSED_PARAM, char **argv) if (pending_sig) goto sigout; #if BASH_WAIT_N - if (one) { + if (one && jp) { /* wait -n waits for one _job_, not one _process_. * date; sleep 3 & sleep 2 | sleep 1 & wait -n; date * should wait for 2 seconds. Not 1 or 3. */ +oneout: + jp->waited = 1; + status = jp->ps[jp->nprocs - 1].ps_status; if (status != -1 && !WIFSTOPPED(status)) { retval = WEXITSTATUS(status); if (WIFSIGNALED(status)) diff --git a/shell/ash_test/ash-misc/wait8.right b/shell/ash_test/ash-misc/wait8.right index 5d29b8cc7dbf..e3ebde532ab8 100644 --- a/shell/ash_test/ash-misc/wait8.right +++ b/shell/ash_test/ash-misc/wait8.right @@ -2,3 +2,5 @@ Test1 (wait with zero exit status of bg process) Test2 (wait with non-zero exit status of bg process) Test3 (pipeline wait for whole job) Ok:0 +Test4 (wait exit code with signal) +Test5 (wait -n exits 127 if nothing to wait for) diff --git a/shell/ash_test/ash-misc/wait8.tests b/shell/ash_test/ash-misc/wait8.tests index d29490260001..453f30a62156 100755 --- a/shell/ash_test/ash-misc/wait8.tests +++ b/shell/ash_test/ash-misc/wait8.tests @@ -45,3 +45,17 @@ fi kill $bg echo Ok:$? + +echo "Test4 (wait exit code with signal)" +wait -n +rc=$? +if [ "$rc" != 143 ]; then + echo "Test4 exit code was not 143 (128+SIGTERM): $rc" +fi + +echo "Test5 (wait -n exits 127 if nothing to wait for)" +wait -n +rc=$? +if [ "$rc" != 127 ]; then + echo "wait -n with nothing to wait was not 127: $rc" +fi -- 2.47.3 _______________________________________________ busybox mailing list [email protected] https://lists.busybox.net/mailman/listinfo/busybox
