summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2017-08-15 20:49:23 +0100
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2017-08-15 20:49:23 +0100
commitddb86759012992fa6471bd738f906a4ed434b69f (patch)
tree2400c5e08f28e9a6295ff0bf8005ebf849083583
parent74aff4106a4272d86c637c472a04efd46bbec07e (diff)
downloadzsh-ddb86759012992fa6471bd738f906a4ed434b69f.tar.gz
zsh-ddb86759012992fa6471bd738f906a4ed434b69f.tar.xz
zsh-ddb86759012992fa6471bd738f906a4ed434b69f.zip
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.
-rw-r--r--ChangeLog6
-rw-r--r--Src/exec.c18
-rw-r--r--Src/zsh.h12
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  <p.w.stephenson@ntlworld.com>
+
+	* 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  <p.stephenson@samsung.com>
 
 	* 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              */