summary refs log tree commit diff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-05-27 21:37:14 +1000
committerHerbert Xu <herbert@gondor.apana.org.au>2010-05-27 21:37:14 +1000
commit207e4c2a322fe0f928944f7004b5b17ae2dceaaa (patch)
tree51b52f1f6065ac676e74931ee7eeae222c6d9d02
parent[EXPAND] Fix corruption of redirections with byte 0x81 (diff)
downloaddash-207e4c2a322fe0f928944f7004b5b17ae2dceaaa.tar.gz
dash-207e4c2a322fe0f928944f7004b5b17ae2dceaaa.zip
[JOBS] Fix wait regression where it does not wait for all jobs
The sigsuspend patch broke wait by making it return after just
one job has completed.  This is because we rely on pendingsigs
to signal work and never clear it until waitcmd finishes.

This patch adds a separate gotsigchld for this purpose so we
can clear it before we start waiting.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to '')
-rw-r--r--ChangeLog1
-rw-r--r--src/jobs.c6
-rw-r--r--src/trap.c8
-rw-r--r--src/trap.h1
4 files changed, 13 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 164eb2e..54d2972 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,7 @@
 	* Do not poplocalvars prematurely on regular utilities.
 	* Move null redirect checks into caller.
 	* Fix popredir on abnormal exit from built-in.
+	* Fix wait regression where it does not wait for all jobs.
 
 2010-05-26  Herbert Xu <herbert@gondor.apana.org.au>
 
diff --git a/src/jobs.c b/src/jobs.c
index a4fada0..060187c 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1124,7 +1124,6 @@ waitproc(int block, int *status)
 	sigset_t mask, oldmask;
 	int flags = block == DOWAIT_BLOCK ? 0 : WNOHANG;
 	int err;
-	int sig;
 
 #if JOBS
 	if (jobctl)
@@ -1132,6 +1131,7 @@ waitproc(int block, int *status)
 #endif
 
 	do {
+		gotsigchld = 0;
 		err = wait3(status, flags, NULL);
 		if (err || !block)
 			break;
@@ -1141,11 +1141,11 @@ waitproc(int block, int *status)
 		sigfillset(&mask);
 		sigprocmask(SIG_SETMASK, &mask, &oldmask);
 
-		while (!(sig = pendingsigs))
+		while (!gotsigchld && !pendingsigs)
 			sigsuspend(&oldmask);
 
 		sigclearmask();
-	} while (sig == SIGCHLD);
+	} while (gotsigchld);
 
 	return err;
 }
diff --git a/src/trap.c b/src/trap.c
index ba32da6..7bd60ab 100644
--- a/src/trap.c
+++ b/src/trap.c
@@ -78,6 +78,8 @@ char sigmode[NSIG - 1];
 static char gotsig[NSIG - 1];
 /* last pending signal */
 volatile sig_atomic_t pendingsigs;
+/* received SIGCHLD */
+int gotsigchld;
 
 extern char *signal_names[];
 
@@ -284,6 +286,12 @@ ignoresig(int signo)
 void
 onsig(int signo)
 {
+	if (signo == SIGCHLD) {
+		gotsigchld = 1;
+		if (!trap[SIGCHLD])
+			return;
+	}
+
 	gotsig[signo - 1] = 1;
 	pendingsigs = signo;
 
diff --git a/src/trap.h b/src/trap.h
index 50fc3ed..bdd7944 100644
--- a/src/trap.h
+++ b/src/trap.h
@@ -39,6 +39,7 @@
 extern int trapcnt;
 extern char sigmode[];
 extern volatile sig_atomic_t pendingsigs;
+extern int gotsigchld;
 
 int trapcmd(int, char **);
 void clear_traps(void);