summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Src/exec.c11
-rw-r--r--Test/E01options.ztst10
3 files changed, 23 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 71f51a966..363a8324e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-05-23  Peter Stephenson  <pws@csr.com>
 
+	* John Buddery: 23461 plus comment and test: fix race
+	setting up multios by blocking SIGCHLD.
+
 	* 23460: Src/exec.c, Src/jobs.c, Test/E01options.ztst:
 	fix longstanding problem with multios attached to a
 	subshell process.
diff --git a/Src/exec.c b/Src/exec.c
index 5aa3dba12..f711f3d30 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1549,20 +1549,29 @@ closemn(struct multio **mfds, int fd)
 	pid_t pid;
 	struct timeval bgtime;
 
+	/*
+	 * We need to block SIGCHLD in case the process
+	 * we are spawning terminates before the job table
+	 * is set up to handle it.
+	 */
+	child_block();
 	if ((pid = zfork(&bgtime))) {
 	    for (i = 0; i < mn->ct; i++)
 		zclose(mn->fds[i]);
 	    zclose(mn->pipe);
-	    if (pid == -1) { 
+	    if (pid == -1) {
 		mfds[fd] = NULL;
+		child_unblock();
 		return;
 	    }
 	    mn->ct = 1;
 	    mn->fds[0] = fd;
 	    addproc(pid, NULL, 1, &bgtime);
+	    child_unblock();
 	    return;
 	}
 	/* pid == 0 */
+	child_unblock();
 	closeallelse(mn);
 	if (mn->rflag) {
 	    /* tee process */
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index 0ce82b3ab..5bbf1b590 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -667,6 +667,16 @@
 >hello
 >hello
 
+# This tests for another race in multios.
+  print 'This test hangs the shell when it fails...' >&8
+  setopt multios
+  echo These are the contents of the file >multio_race.out
+  multio_race_fn() { cat; }
+  multio_race_fn <$(echo multio_race.out multio_race.out)
+0:Fix for race with input multios
+>These are the contents of the file
+>These are the contents of the file
+
 # tried this with other things, but not on its own, so much.
   unsetopt nomatch
   print with nonomatch: flooble*