zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: zsh-workers@zsh.org
Subject: Re: Fwd (potential regression in 5.0.3): Bug#732726: zsh function freeze
Date: Sat, 21 Dec 2013 17:34:59 -0800	[thread overview]
Message-ID: <131221173459.ZM1039@torch.brasslantern.com> (raw)
In-Reply-To: <20131221223424.6b7a55a7@pws-pc.ntlworld.com>

On Dec 21, 10:34pm, Peter Stephenson wrote:
}
} Unfortunately it (the patch in 32171) doesn't fix the problem for me.

Drat.

} I think we're forking inside execcmd() after adding pipes[0] to the
} filelist for thisjob.  This subshell is what's going to form the LHS of
} the pipeline --- and we entersubsh() which will clear the job table.
} So I think we need to salvage the filelist from the job table and remove
} the pipe file descriptors in the danger cases, which I take to be the
} places where we were handling subsh_close in the old version of the code
} (where we are handling nested shell constructs of some sort).

I wondered if that would be necessary, but couldn't ever manage to get
DPUTS() statements in those two places to print anything, so concluded
that the issue was in the place that I did patch.

What concerns me is whether we might be closing too many file descriptors
if we remove all is_fd entries from filelist at that point, but if that's
in the parent that's going to do nothing but wait for the child it should
be OK.
 
} The following does seem to fix the hang here and not cause any new test
} failures.  Note it includes your code change, but not your regression
} test (you hadn't pushed either yet last I looked).

Argh!  Did "git commit" but forgot "git push".  Did that now.

Here's your new bit of 32175 plus an additional regression test (fails
with just 32171 but succeeds after 32175).


diff --git a/Src/exec.c b/Src/exec.c
index 4480033..f16cfd3 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2389,7 +2389,7 @@ static void
 execcmd(Estate state, int input, int output, int how, int last1)
 {
     HashNode hn = NULL;
-    LinkList args;
+    LinkList args, filelist = NULL;
     LinkNode node;
     Redir fn;
     struct multio *mfds[10];
@@ -2911,6 +2911,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	    flags |= ESUB_KEEPTRAP;
 	if (type == WC_SUBSH && !(how & Z_ASYNC))
 	    flags |= ESUB_JOB_CONTROL;
+	filelist = jobtab[thisjob].filelist;
 	entersubsh(flags);
 	close(synch[1]);
 	forked = 1;
@@ -3264,6 +3265,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
 
 	    if (is_shfunc) {
 		/* It's a shell function */
+		pipecleanfilelist(filelist);
 		execshfunc((Shfunc) hn, args);
 	    } else {
 		/* It's a builtin */
@@ -3342,6 +3344,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
 		DPUTS(varspc,
 		      "BUG: assignment before complex command");
 		list_pipe = 0;
+		pipecleanfilelist(filelist);
 		/* If we're forked (and we should be), no need to return */
 		DPUTS(last1 != 1 && !forked, "BUG: not exiting?");
 		DPUTS(type != WC_SUBSH, "Not sure what we're doing.");
diff --git a/Src/jobs.c b/Src/jobs.c
index 371b8eb..a321172 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1173,6 +1173,30 @@ addfilelist(const char *name, int fd)
     zaddlinknode(ll, jf);
 }
 
+/* Clean up pipes no longer needed associated with a job */
+
+/**/
+void
+pipecleanfilelist(LinkList filelist)
+{
+    LinkNode node;
+
+    if (!filelist)
+	return;
+    node = firstnode(filelist);
+    while (node) {
+	Jobfile jf = (Jobfile)getdata(node);
+	if (jf->is_fd) {
+	    LinkNode next = nextnode(node);
+	    zclose(jf->u.fd);
+	    (void)remnode(filelist, node);
+	    zfree(jf, sizeof(*jf));
+	    node = next;
+	} else
+	    incnode(node);
+    }
+}
+
 /* Finished with list of files for a job */
 
 /**/
@@ -1415,19 +1439,7 @@ zwaitjob(int job, int wait_cmd)
 	     * 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);
-		}
-	    }
+	    pipecleanfilelist(jn->filelist);
 	}
 	while (!errflag && jn->stat &&
 	       !(jn->stat & STAT_DONE) &&
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index 61d24fe..6abfd8b 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -207,10 +207,12 @@ F:This similar test was triggering a reproducible failure with pipestatus.
   coproc { read -Et 5 || kill -INT $$ }
   print -u $ZTST_fd 'This test takes 5 seconds to fail...'
   { printf "%d\n" {1..20000} } | ( read -E )
+  hang(){ printf "%d\n" {2..20000} | cat }; hang | ( read -E )
   print -p done
   read -Ep
 0:Bug regression: piping a shell construct to an external process may hang
 >1
+>2
 >done
 F:This test checks for a file descriptor leak that could cause the left
 F:side of a pipe to block on write after the right side has exited


  reply	other threads:[~2013-12-22  1:35 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-20 19:24 Axel Beckert
2013-12-20 20:27 ` Bart Schaefer
2013-12-20 20:49   ` Axel Beckert
2013-12-20 23:51   ` Vincent Lefevre
2013-12-20 23:59     ` Vincent Lefevre
2013-12-21  0:12       ` Vincent Lefevre
2013-12-21  2:19         ` Bart Schaefer
2013-12-21  3:42           ` Bart Schaefer
2013-12-21  7:16             ` Bart Schaefer
2013-12-21 18:08             ` Peter Stephenson
2013-12-21 20:57               ` Bart Schaefer
2013-12-21 22:34                 ` Peter Stephenson
2013-12-22  1:34                   ` Bart Schaefer [this message]
2013-12-23  2:06                     ` (potential regression in 5.0.3) Paul Ackersviller
2013-12-23  5:47                       ` Bart Schaefer
2014-01-02 18:06                     ` Fwd (potential regression in 5.0.3): Bug#732726: zsh function freeze Peter Stephenson
2014-01-02 20:40                       ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=131221173459.ZM1039@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).