summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/jobs.c25
-rw-r--r--Test/D03procsubst.ztst8
3 files changed, 40 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 8d7e62a1b..e5777bc52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-07-19  Peter Stephenson  <p.stephenson@samsung.com>
+
+	* 31536 (plus memory leak fixed, plus test code):
+	Src/jobs.c, Test/D03procsubst.ztst: fix hang in 31528 by
+	closing process substitution file descriptors when waiting
+	for job to finish.
+
 2013-07-17  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* 31528: Src/exec.c, Src/jobs.c, Src/zsh.h: use job table
diff --git a/Src/jobs.c b/Src/jobs.c
index a1955bb0f..e1b24b2c9 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1368,6 +1368,31 @@ zwaitjob(int job, int wait_cmd)
 	jn->stat |= STAT_LOCKED;
 	if (jn->stat & STAT_CHANGED)
 	    printjob(jn, !!isset(LONGLISTJOBS), 1);
+	if (jn->filelist) {
+	    /*
+	     * The main shell is finished with any file descriptors used
+	     * for process substitution associated with this job: close
+	     * them to indicate to listeners there's no more input.
+	     *
+	     * Note we can't safely delete temporary files yet as these
+	     * are directly visible to other processes.  However,
+	     * we can't deadlock on the fact that those still exist, so
+	     * that's not a problem.
+	     */
+	    LinkNode node = firstnode(jn->filelist);
+	    while (node) {
+		Jobfile jf = (Jobfile)getdata(node);
+		if (jf->is_fd) {
+		    LinkNode next = nextnode(node);
+		    (void)remnode(jn->filelist, node);
+		    zclose(jf->u.fd);
+		    zfree(jf, sizeof(*jf));
+		    node = next;
+		} else {
+		    incnode(node);
+		}
+	    }
+	}
 	while (!errflag && jn->stat &&
 	       !(jn->stat & STAT_DONE) &&
 	       !(interact && (jn->stat & STAT_STOPPED))) {
diff --git a/Test/D03procsubst.ztst b/Test/D03procsubst.ztst
index 88fa902bb..c763f6e0f 100644
--- a/Test/D03procsubst.ztst
+++ b/Test/D03procsubst.ztst
@@ -107,3 +107,11 @@
 >third: This becomes argument three
 >fourth: and this argument four
 
+  () {
+     # Make sure we don't close the file descriptor too early
+     eval 'print "Execute a complicated command first" | sed s/command/order/'
+     cat $1
+  } <(echo This line was brought to you by the letters F and D)
+0:Process substitution as anonymous function argument
+>Execute a complicated order first
+>This line was brought to you by the letters F and D