From aede5c52bf557f89d1d09fa5430186af6e295241 Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Sat, 21 Dec 2013 17:41:21 -0800
Subject: 32176: plug additional deadlock-inducing pipe descriptor leaks
---
Src/exec.c | 5 ++++-
Src/jobs.c | 38 +++++++++++++++++++++++++-------------
2 files changed, 29 insertions(+), 14 deletions(-)
(limited to 'Src')
diff --git a/Src/exec.c b/Src/exec.c
index 44800339f..f16cfd391 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 371b8eb32..a32117217 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) &&
--
cgit 1.4.1