about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <p.stephenson@samsung.com>2022-03-30 09:28:43 +0100
committerPeter Stephenson <p.stephenson@samsung.com>2022-03-30 09:28:43 +0100
commit98e46340867028808e71e7f3373881cb7e5b6764 (patch)
treece804301a1890959e620dabf3e87da5a63503f80 /Src
parentf11227f78d8d477048194df5b93dfe315d4b1588 (diff)
downloadzsh-98e46340867028808e71e7f3373881cb7e5b6764.tar.gz
zsh-98e46340867028808e71e7f3373881cb7e5b6764.tar.xz
zsh-98e46340867028808e71e7f3373881cb7e5b6764.zip
49906 (Bart), 49911: Fixes to querying jobs in subshell.
Don't attempt to query invalid job off end of table, resulting in
crashes from $jobtstates.

If background task started in subshell, look at tatsks within subshell
instead of main shell.  Document and add test.
Diffstat (limited to 'Src')
-rw-r--r--Src/exec.c1
-rw-r--r--Src/jobs.c20
2 files changed, 21 insertions, 0 deletions
diff --git a/Src/exec.c b/Src/exec.c
index 70cbfc97f..27d49e005 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1689,6 +1689,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
     execpline2(state, code, how, opipe[0], ipipe[1], last1);
     pline_level--;
     if (how & Z_ASYNC) {
+	clearoldjobtab();
 	lastwj = newjob;
 
         if (thisjob == list_pipe_job)
diff --git a/Src/jobs.c b/Src/jobs.c
index 18e43f03c..af0a1233d 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -1718,8 +1718,15 @@ clearjobtab(int monitor)
 	/* Don't report any job we're part of */
 	if (thisjob != -1 && thisjob < oldmaxjob)
 	    memset(oldjobtab+thisjob, 0, sizeof(struct job));
+
+	/* oldmaxjob is now the size of the table, but outside
+	 * this function, it's used as a job number, which must
+	 * be the largest index available in the table.
+	 */
+	--oldmaxjob;
     }
 
+
     memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */
     maxjob = 0;
 
@@ -1733,6 +1740,18 @@ clearjobtab(int monitor)
     thisjob = initjob();
 }
 
+/* In a subshell, decide we want our own job table after all. */
+
+/**/
+mod_export void
+clearoldjobtab(void)
+{
+    if (oldjobtab)
+	free(oldjobtab);
+    oldjobtab = NULL;
+    oldmaxjob = 0;
+}
+
 static int initnewjob(int i)
 {
     jobtab[i].stat = STAT_INUSE;
@@ -2449,6 +2468,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
 	case BIN_BG:
 	case BIN_WAIT:
 	    if (func == BIN_BG) {
+		clearoldjobtab();
 		jobtab[job].stat |= STAT_NOSTTY;
 		jobtab[job].stat &= ~STAT_CURSH;
 	    }