From ddb86759012992fa6471bd738f906a4ed434b69f Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Tue, 15 Aug 2017 20:49:23 +0100
Subject: posted but has not shown up: fix fd problem in subshell.
Record fd's that have been saved in fdtable and if the shell
forks close them as they will never be restored.
---
ChangeLog | 6 ++++++
Src/exec.c | 18 +++++++++++++++---
Src/zsh.h | 12 ++++++++++++
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 9fec281a9..6a9be8cc7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2017-08-15 Peter Stephenson
+
+ * posted twice but has not shown up: Src/exec.c, Src/zsh.h:
+ record file desriptors that remain open to save ones in the
+ range 0 to 9 in fdtable and close them on forking.
+
2017-08-14 Peter Stephenson
* Phil: 4152: Src/Modules/pcre.c, Test/V07pcre.ztst: fix big
diff --git a/Src/exec.c b/Src/exec.c
index f339dd6d0..9996dffed 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -972,7 +972,7 @@ enum {
static void
entersubsh(int flags)
{
- int sig, monitor, job_control_ok;
+ int i, sig, monitor, job_control_ok;
if (!(flags & ESUB_KEEPTRAP))
for (sig = 0; sig < SIGCOUNT; sig++)
@@ -1083,6 +1083,14 @@ entersubsh(int flags)
opts[MONITOR] = 0;
opts[USEZLE] = 0;
zleactive = 0;
+ /*
+ * If we've saved fd's for later restoring, we're never going
+ * to restore them now, so just close them.
+ */
+ for (i = 10; i <= max_zsh_fd; i++) {
+ if (fdtable[i] & FDT_SAVED_MASK)
+ zclose(i);
+ }
if (flags & ESUB_PGRP)
clearjobtab(monitor);
get_usage();
@@ -2318,6 +2326,9 @@ addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
return;
}
save[fd1] = fdN;
+ DPUTS(fdtable[fdN] != FDT_INTERNAL,
+ "Saved file descriptor not marked as internal");
+ fdtable[fdN] |= FDT_SAVED_MASK;
}
}
}
@@ -3575,7 +3586,8 @@ execcmd_exec(Estate state, Execcmd_params eparams,
}
if (!bad && fn->fd1 <= max_zsh_fd) {
if (fn->fd1 >= 10 &&
- fdtable[fn->fd1] == FDT_INTERNAL)
+ (fdtable[fn->fd1] & FDT_TYPE_MASK) ==
+ FDT_INTERNAL)
bad = 3;
}
}
@@ -4270,7 +4282,7 @@ closem(int how)
for (i = 10; i <= max_zsh_fd; i++)
if (fdtable[i] != FDT_UNUSED &&
- (how == FDT_UNUSED || fdtable[i] == how)) {
+ (how == FDT_UNUSED || (fdtable[i] & FDT_TYPE_MASK) == how)) {
if (i == SHTTY)
SHTTY = -1;
zclose(i);
diff --git a/Src/zsh.h b/Src/zsh.h
index ccd11db3d..91e8d7f8c 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -456,6 +456,18 @@ enum {
#define FDT_PROC_SUBST 7
#endif
+/*
+ * Mask to get the basic FDT type.
+ */
+#define FDT_TYPE_MASK 15
+
+/*
+ * Bit flag that fd is saved for later restoration.
+ * Currently this is only use with FDT_INTERNAL. We use this fact so as
+ * not to have to mask checks against other types.
+ */
+#define FDT_SAVED_MASK 16
+
/* Flags for input stack */
#define INP_FREE (1<<0) /* current buffer can be free'd */
#define INP_ALIAS (1<<1) /* expanding alias or history */
--
cgit 1.4.1