[git commit] ash: add "wait -n" bashism

Denys Vlasenko vda.linux at googlemail.com
Wed Mar 27 14:52:17 UTC 2019


commit: https://git.busybox.net/busybox/commit/?id=966f087ab41e555fb40a158e7feae7603b31d450
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
waitcmd                                              205     288     +83
dowait                                               405     444     +39
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 122/0)             Total: 122 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/ash.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 47 insertions(+), 6 deletions(-)

diff --git a/shell/ash.c b/shell/ash.c
index a4394d756..b1499b037 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3522,7 +3522,7 @@ struct procstat {
 
 struct job {
 	struct procstat ps0;    /* status of process */
-	struct procstat *ps;    /* status or processes when more than one */
+	struct procstat *ps;    /* status of processes when more than one */
 #if JOBS
 	int stopstatus;         /* status of a stopped job */
 #endif
@@ -4235,6 +4235,9 @@ wait_block_or_sig(int *status)
 #define DOWAIT_NONBLOCK 0
 #define DOWAIT_BLOCK    1
 #define DOWAIT_BLOCK_OR_SIG 2
+#if ENABLE_ASH_BASH_COMPAT
+# define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
+#endif
 
 static int
 dowait(int block, struct job *job)
@@ -4242,7 +4245,11 @@ dowait(int block, struct job *job)
 	int pid;
 	int status;
 	struct job *jp;
-	struct job *thisjob = NULL;
+	struct job *thisjob;
+#if ENABLE_ASH_BASH_COMPAT
+	bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
+	block = (block & ~DOWAIT_JOBSTATUS);
+#endif
 
 	TRACE(("dowait(0x%x) called\n", block));
 
@@ -4279,10 +4286,10 @@ dowait(int block, struct job *job)
 	}
 	TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
 				pid, status, errno, strerror(errno)));
+	thisjob = NULL;
 	if (pid <= 0)
 		goto out;
 
-	thisjob = NULL;
 	for (jp = curjob; jp; jp = jp->prev_job) {
 		int jobstate;
 		struct procstat *ps;
@@ -4341,6 +4348,13 @@ dowait(int block, struct job *job)
  out:
 	INT_ON;
 
+#if ENABLE_ASH_BASH_COMPAT
+	if (want_jobexitstatus) {
+		pid = -1;
+		if (thisjob && thisjob->state == JOBDONE)
+			pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
+	}
+#endif
 	if (thisjob && thisjob == job) {
 		char s[48 + 1];
 		int len;
@@ -4523,15 +4537,24 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
 	struct job *job;
 	int retval;
 	struct job *jp;
-
+#if ENABLE_ASH_BASH_COMPAT
+	int status;
+	char one = nextopt("n");
+#else
 	nextopt(nullstr);
+#endif
 	retval = 0;
 
 	argv = argptr;
-	if (!*argv) {
-		/* wait for all jobs */
+	if (!argv[0]) {
+		/* wait for all jobs / one job if -n */
 		for (;;) {
 			jp = curjob;
+#if ENABLE_ASH_BASH_COMPAT
+			if (one && !jp)
+				/* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
+				retval = 127;
+#endif
 			while (1) {
 				if (!jp) /* no running procs */
 					goto ret;
@@ -4547,13 +4570,31 @@ waitcmd(int argc UNUSED_PARAM, char **argv)
 	 * with an exit status greater than 128, immediately after which
 	 * the trap is executed."
 	 */
+#if ENABLE_ASH_BASH_COMPAT
+			status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
+#else
 			dowait(DOWAIT_BLOCK_OR_SIG, NULL);
+#endif
 	/* if child sends us a signal *and immediately exits*,
 	 * dowait() returns pid > 0. Check this case,
 	 * not "if (dowait() < 0)"!
 	 */
 			if (pending_sig)
 				goto sigout;
+#if ENABLE_ASH_BASH_COMPAT
+			if (one) {
+				/* 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.
+				 */
+				if (status != -1 && !WIFSTOPPED(status)) {
+					retval = WEXITSTATUS(status);
+					if (WIFSIGNALED(status))
+						retval = WTERMSIG(status) + 128;
+					goto ret;
+				}
+			}
+#endif
 		}
 	}
 


More information about the busybox-cvs mailing list