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 slight size increase:
function                                             old     new   delta
waitcmd                                              334     397     +63
waitone                                              449     399     -50
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 63/-50)             Total: 13 bytes

Signed-off-by: Dominique Martinet <[email protected]>
---
Note this is still smaller than two commits before:
function                                             old     new   delta
waitone                                                -     399    +399
waitcmd                                              277     397    +120
dowait                                               608      80    -528
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 519/-528)           Total: -9 bytes

 shell/ash.c                         | 46 ++++++++++++++++-------------
 shell/ash_test/ash-misc/wait8.tests | 11 +++++++
 2 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index 4f5ca0d02fb7..877e09bf88d7 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,33 +4559,29 @@ 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;
                }
-       } 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;
@@ -4594,11 +4590,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
@@ -4780,12 +4776,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;
@@ -4802,7 +4803,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
@@ -4818,6 +4819,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
                                 *  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.tests 
b/shell/ash_test/ash-misc/wait8.tests
index 438fd2cb4c4f..45437b5e7e96 100755
--- a/shell/ash_test/ash-misc/wait8.tests
+++ b/shell/ash_test/ash-misc/wait8.tests
@@ -45,3 +45,14 @@ fi
 
 kill $bg
 echo Ok:$?
+wait -n
+rc=$?
+if [ "$rc" != 143 ]; then
+       echo "Test1 exit code was not 143 (128+SIGTERM): $rc"
+fi
+
+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