about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2012-10-11 16:36:14 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2012-10-11 16:36:14 +0000
commitad92cb3203e5d95be91019633e8f1f5835b12794 (patch)
treec5bc5532661018ea7117187449b0d796c028ba23
parent34ed3eaecd3fedb8733b82c27dccba024608bf5f (diff)
downloadzsh-ad92cb3203e5d95be91019633e8f1f5835b12794.tar.gz
zsh-ad92cb3203e5d95be91019633e8f1f5835b12794.tar.xz
zsh-ad92cb3203e5d95be91019633e8f1f5835b12794.zip
30724: shell code optimisd to use execsimple() doesn't have a valid thisjob
-rw-r--r--ChangeLog7
-rw-r--r--Src/exec.c27
-rw-r--r--Src/jobs.c8
3 files changed, 37 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 9768aa8e0..5a69f0174 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-11  Peter Stephenson  <pws@csr.com>
+
+	* 30724: Src/exec.c, Src/jobs.c: shell code optimised to use
+	execsimple() doesn't have a valid thisjob.
+
 2012-10-09  Peter Stephenson  <pws@csr.com>
 
 	* users/17318: Src/Zle/zle_utils.c: don't increment the undo
@@ -255,5 +260,5 @@
 
 *****************************************************
 * This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.5743 $
+* $Revision: 1.5744 $
 *****************************************************
diff --git a/Src/exec.c b/Src/exec.c
index 0f7c84a9f..b2224cfb3 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -404,7 +404,17 @@ execcursh(Estate state, int do_exec)
     /* Skip word only used for try/always */
     state->pc++;
 
-    if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob))
+    /*
+     * The test thisjob != -1 was added because sometimes thisjob
+     * can be invalid at this point.  The case in question was
+     * in a precmd function after operations involving background
+     * jobs.
+     *
+     * This is because sometimes we bypass job control to execute
+     * very simple functions via execssimple().
+     */
+    if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
+	!hasprocs(thisjob))
 	deletejob(jobtab + thisjob, 0);
     cmdpush(CS_CURSH);
     execlist(state, 1, do_exec);
@@ -1064,7 +1074,7 @@ static int
 execsimple(Estate state)
 {
     wordcode code = *state->pc++;
-    int lv;
+    int lv, otj;
 
     if (errflag)
 	return (lastval = 1);
@@ -1075,6 +1085,13 @@ execsimple(Estate state)
 
     code = wc_code(*state->pc++);
 
+    /*
+     * Because we're bypassing job control, ensure the called
+     * code doesn't see the current job.
+     */
+    otj = thisjob;
+    thisjob = -1;
+
     if (code == WC_ASSIGN) {
 	cmdoutval = 0;
 	addvars(state, state->pc - 1, 0);
@@ -1086,6 +1103,8 @@ execsimple(Estate state)
     } else
 	lv = (execfuncs[code - WC_CURSH])(state, 0);
 
+    thisjob = otj;
+
     return lastval = lv;
 }
 
@@ -4313,7 +4332,9 @@ execshfunc(Shfunc shf, LinkList args)
     if (errflag)
 	return;
 
-    if (!list_pipe && thisjob != list_pipe_job && !hasprocs(thisjob)) {
+    /* thisjob may be invalid if we're called via execsimple: see execcursh */
+    if (!list_pipe && thisjob != -1 && thisjob != list_pipe_job &&
+	!hasprocs(thisjob)) {
 	/* Without this deletejob the process table *
 	 * would be filled by a recursive function. */
 	last_file_list = jobtab[thisjob].filelist;
diff --git a/Src/jobs.c b/Src/jobs.c
index ddd997c49..0464d18d8 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -209,7 +209,13 @@ findproc(pid_t pid, Job *jptr, Process *pptr, int aux)
 int
 hasprocs(int job)
 {
-    Job jn = jobtab + job;
+    Job jn;
+
+    if (job < 0) {
+	DPUTS(1, "job number invalid in hasprocs");
+	return 0;
+    }
+    jn = jobtab + job;
 
     return jn->procs || jn->auxprocs;
 }