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

Reply via email to