f686d7
From bbeb06a37ba58f6905803d32a26fb00953459301 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Thu, 20 Mar 2014 07:56:30 -0700
f686d7
Subject: [PATCH 1/8] 32500: handle interrupts during pattern matching
f686d7
f686d7
Upstream-commit: 8672d19f0c0f25569e233bbd466b6c39f60c7a55
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/pattern.c | 8 +++++++-
f686d7
 1 file changed, 7 insertions(+), 1 deletion(-)
f686d7
f686d7
diff --git a/Src/pattern.c b/Src/pattern.c
f686d7
index b74a08a..b93b064 100644
f686d7
--- a/Src/pattern.c
f686d7
+++ b/Src/pattern.c
f686d7
@@ -2128,6 +2128,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen,
f686d7
 
f686d7
 	return ret;
f686d7
     } else {
f686d7
+	int q = queue_signal_level();
f686d7
+
f686d7
 	/*
f686d7
 	 * Test for a `must match' string, unless we're scanning for a match
f686d7
 	 * in which case we don't need to do this each time.
f686d7
@@ -2175,6 +2177,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen,
f686d7
 
f686d7
 	patinput = patinstart;
f686d7
 
f686d7
+	dont_queue_signals();
f686d7
+
f686d7
 	if (patmatch((Upat)progstr)) {
f686d7
 	    /*
f686d7
 	     * we were lazy and didn't save the globflags if an exclusion
f686d7
@@ -2311,6 +2315,8 @@ pattryrefs(Patprog prog, char *string, int stringlen, int unmetalen,
f686d7
 	} else
f686d7
 	    ret = 0;
f686d7
 
f686d7
+	restore_queue_signals(q);
f686d7
+
f686d7
 	if (tryalloced)
f686d7
 	    zfree(tryalloced, unmetalen + unmetalenp);
f686d7
 
f686d7
@@ -2390,7 +2396,7 @@ patmatch(Upat prog)
f686d7
     zrange_t from, to, comp;
f686d7
     patint_t nextch;
f686d7
 
f686d7
-    while  (scan) {
f686d7
+    while  (scan && !errflag) {
f686d7
 	next = PATNEXT(scan);
f686d7
 
f686d7
 	if (!globdots && P_NOTDOT(scan) && patinput == patinstart &&
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From c3eeba82d560005d830862dace8d771e712693e6 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Sun, 9 Aug 2015 00:50:36 -0700
f686d7
Subject: [PATCH 2/8] 36022 fix bug that some loop constructs could not be
f686d7
 interrupted, revise signal queueing
f686d7
f686d7
There are two underlying ideas here:  (1) Keeping signals queued around
f686d7
anything that's doing memory management (including push/pop of the heap)
f686d7
has become crucial.  (2) Anytime the shell is going to run a command, be
f686d7
it buitin or external, it must be both safe and necessary to process any
f686d7
queued signals, so that the apparent order of signal arrival and command
f686d7
execution is preserved.
f686d7
f686d7
Upstream-commit: 9958684574bf8b0ecec6983cca57f3fa3dd7cd63
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/exec.c    | 43 ++++++++++++++++++++++++++++++++++++++-----
f686d7
 Src/init.c    |  5 +++++
f686d7
 Src/input.c   |  9 +++++++++
f686d7
 Src/loop.c    | 36 ++++++++++++++++++++++++++++++++++--
f686d7
 Src/parse.c   |  8 ++++++++
f686d7
 Src/signals.c |  8 ++++++--
f686d7
 6 files changed, 100 insertions(+), 9 deletions(-)
f686d7
f686d7
diff --git a/Src/exec.c b/Src/exec.c
f686d7
index 7817a64..cff1a24 100644
f686d7
--- a/Src/exec.c
f686d7
+++ b/Src/exec.c
f686d7
@@ -1108,8 +1108,12 @@ execsimple(Estate state)
f686d7
 	    fflush(xtrerr);
f686d7
 	}
f686d7
 	lv = (errflag ? errflag : cmdoutval);
f686d7
-    } else
f686d7
+    } else {
f686d7
+	int q = queue_signal_level();
f686d7
+	dont_queue_signals();
f686d7
 	lv = (execfuncs[code - WC_CURSH])(state, 0);
f686d7
+	restore_queue_signals(q);
f686d7
+     }
f686d7
 
f686d7
     thisjob = otj;
f686d7
 
f686d7
@@ -1141,6 +1145,8 @@ execlist(Estate state, int dont_change_job, int exiting)
f686d7
      */
f686d7
     int oldnoerrexit = noerrexit;
f686d7
 
f686d7
+    queue_signals();
f686d7
+
f686d7
     cj = thisjob;
f686d7
     old_pline_level = pline_level;
f686d7
     old_list_pipe = list_pipe;
f686d7
@@ -1391,6 +1397,8 @@ sublist_done:
f686d7
 	/* Make sure this doesn't get executed again. */
f686d7
 	sigtrapped[SIGEXIT] = 0;
f686d7
     }
f686d7
+
f686d7
+    unqueue_signals();
f686d7
 }
f686d7
 
f686d7
 /* Execute a pipeline.                                                *
f686d7
@@ -1419,6 +1427,14 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
     else if (slflags & WC_SUBLIST_NOT)
f686d7
 	last1 = 0;
f686d7
 
f686d7
+    /* If trap handlers are allowed to run here, they may start another
f686d7
+     * external job in the middle of us starting this one, which can
f686d7
+     * result in jobs being reaped before their job table entries have
f686d7
+     * been initialized, which in turn leads to waiting forever for
f686d7
+     * jobs that no longer exist.  So don't do that.
f686d7
+     */
f686d7
+    queue_signals();
f686d7
+
f686d7
     pj = thisjob;
f686d7
     ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
f686d7
     child_block();
f686d7
@@ -1431,6 +1447,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
      */
f686d7
     if ((thisjob = newjob = initjob()) == -1) {
f686d7
 	child_unblock();
f686d7
+	unqueue_signals();
f686d7
 	return 1;
f686d7
     }
f686d7
     if (how & Z_TIMED)
f686d7
@@ -1486,6 +1503,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
 	else
f686d7
 	    spawnjob();
f686d7
 	child_unblock();
f686d7
+	unqueue_signals();
f686d7
 	/* Executing background code resets shell status */
f686d7
 	return lastval = 0;
f686d7
     } else {
f686d7
@@ -1543,15 +1561,18 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
 		}
f686d7
 		if (!(jn->stat & STAT_LOCKED)) {
f686d7
 		    updated = hasprocs(thisjob);
f686d7
-		    waitjobs();
f686d7
+		    waitjobs();		/* deals with signal queue */
f686d7
 		    child_block();
f686d7
 		} else
f686d7
 		    updated = 0;
f686d7
 		if (!updated &&
f686d7
 		    list_pipe_job && hasprocs(list_pipe_job) &&
f686d7
 		    !(jobtab[list_pipe_job].stat & STAT_STOPPED)) {
f686d7
+		    int q = queue_signal_level();
f686d7
 		    child_unblock();
f686d7
+		    dont_queue_signals();
f686d7
 		    child_block();
f686d7
+		    restore_queue_signals(q);
f686d7
 		}
f686d7
 		if (list_pipe_child &&
f686d7
 		    jn->stat & STAT_DONE &&
f686d7
@@ -1631,6 +1652,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
 		    break;
f686d7
 	    }
f686d7
 	    child_unblock();
f686d7
+	    unqueue_signals();
f686d7
 
f686d7
 	    if (list_pipe && (lastval & 0200) && pj >= 0 &&
f686d7
 		(!(jn->stat & STAT_INUSE) || (jn->stat & STAT_DONE))) {
f686d7
@@ -3192,6 +3214,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
f686d7
 	    fflush(xtrerr);
f686d7
 	}
f686d7
     } else if (isset(EXECOPT) && !errflag) {
f686d7
+	int q = queue_signal_level();
f686d7
 	/*
f686d7
 	 * We delay the entersubsh() to here when we are exec'ing
f686d7
 	 * the current shell (including a fake exec to run a builtin then
f686d7
@@ -3210,7 +3233,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
f686d7
 	if (type >= WC_CURSH) {
f686d7
 	    if (last1 == 1)
f686d7
 		do_exec = 1;
f686d7
+	    dont_queue_signals();
f686d7
 	    lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
f686d7
+	    restore_queue_signals(q);
f686d7
 	} else if (is_builtin || is_shfunc) {
f686d7
 	    LinkList restorelist = 0, removelist = 0;
f686d7
 	    /* builtin or shell function */
f686d7
@@ -3269,7 +3294,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
f686d7
 		/* It's a builtin */
f686d7
 		if (forked)
f686d7
 		    closem(FDT_INTERNAL);
f686d7
+		dont_queue_signals();
f686d7
 		lastval = execbuiltin(args, (Builtin) hn);
f686d7
+		restore_queue_signals(q);
f686d7
 #ifdef PATH_DEV_FD
f686d7
 		closem(FDT_PROC_SUBST);
f686d7
 #endif
f686d7
@@ -4415,11 +4442,9 @@ execshfunc(Shfunc shf, LinkList args)
f686d7
     if ((osfc = sfcontext) == SFC_NONE)
f686d7
 	sfcontext = SFC_DIRECT;
f686d7
     xtrerr = stderr;
f686d7
-    unqueue_signals();
f686d7
 
f686d7
     doshfunc(shf, args, 0);
f686d7
 
f686d7
-    queue_signals();
f686d7
     sfcontext = osfc;
f686d7
     free(cmdstack);
f686d7
     cmdstack = ocs;
f686d7
@@ -4614,6 +4639,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
f686d7
     static int funcdepth;
f686d7
 #endif
f686d7
 
f686d7
+    queue_signals();	/* Lots of memory and global state changes coming */
f686d7
+
f686d7
     pushheap();
f686d7
 
f686d7
     oargv0 = NULL;
f686d7
@@ -4814,6 +4841,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
f686d7
     }
f686d7
     popheap();
f686d7
 
f686d7
+    unqueue_signals();
f686d7
+
f686d7
     if (exit_pending) {
f686d7
 	if (locallevel > forklevel) {
f686d7
 	    /* Still functions to return: force them to do so. */
f686d7
@@ -4844,6 +4873,8 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
f686d7
     int cont, ouu;
f686d7
     char *ou;
f686d7
 
f686d7
+    queue_signals();
f686d7
+
f686d7
     ou = zalloc(ouu = underscoreused);
f686d7
     if (ou)
f686d7
 	memcpy(ou, zunderscore, underscoreused);
f686d7
@@ -4865,12 +4896,14 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
f686d7
 	wrap = wrap->next;
f686d7
     }
f686d7
     startparamscope();
f686d7
-    execode(prog, 1, 0, "shfunc");
f686d7
+    execode(prog, 1, 0, "shfunc");	/* handles signal unqueueing */
f686d7
     if (ou) {
f686d7
 	setunderscore(ou);
f686d7
 	zfree(ou, ouu);
f686d7
     }
f686d7
     endparamscope();
f686d7
+
f686d7
+    unqueue_signals();
f686d7
 }
f686d7
 
f686d7
 /* Search fpath for an undefined function.  Finds the file, and returns the *
f686d7
diff --git a/Src/init.c b/Src/init.c
f686d7
index 78f171d..df42349 100644
f686d7
--- a/Src/init.c
f686d7
+++ b/Src/init.c
f686d7
@@ -105,6 +105,7 @@ loop(int toplevel, int justonce)
f686d7
     Eprog prog;
f686d7
     int err, non_empty = 0;
f686d7
 
f686d7
+    queue_signals();
f686d7
     pushheap();
f686d7
     if (!toplevel)
f686d7
 	lexsave();
f686d7
@@ -118,7 +119,9 @@ loop(int toplevel, int justonce)
f686d7
 	    if (interact && toplevel) {
f686d7
 	        int hstop = stophist;
f686d7
 		stophist = 3;
f686d7
+		unqueue_signals();
f686d7
 		preprompt();
f686d7
+		queue_signals();
f686d7
 		if (stophist != 3)
f686d7
 		    hbegin(1);
f686d7
 		else
f686d7
@@ -197,6 +200,7 @@ loop(int toplevel, int justonce)
f686d7
 	if (((!interact || sourcelevel) && errflag) || retflag)
f686d7
 	    break;
f686d7
 	if (isset(SINGLECOMMAND) && toplevel) {
f686d7
+	    dont_queue_signals();
f686d7
 	    if (sigtrapped[SIGEXIT])
f686d7
 		dotrap(SIGEXIT);
f686d7
 	    exit(lastval);
f686d7
@@ -208,6 +212,7 @@ loop(int toplevel, int justonce)
f686d7
     if (!toplevel)
f686d7
 	lexrestore();
f686d7
     popheap();
f686d7
+    unqueue_signals();
f686d7
 
f686d7
     if (err)
f686d7
 	return LOOP_ERROR;
f686d7
diff --git a/Src/input.c b/Src/input.c
f686d7
index 5b782dc..dcff78a 100644
f686d7
--- a/Src/input.c
f686d7
+++ b/Src/input.c
f686d7
@@ -140,14 +140,17 @@ shingetline(void)
f686d7
     int c;
f686d7
     char buf[BUFSIZ];
f686d7
     char *p;
f686d7
+    int q = queue_signal_level();
f686d7
 
f686d7
     p = buf;
f686d7
     for (;;) {
f686d7
+	dont_queue_signals();
f686d7
 	do {
f686d7
 	    errno = 0;
f686d7
 	    c = fgetc(bshin);
f686d7
 	} while (c < 0 && errno == EINTR);
f686d7
 	if (c < 0 || c == '\n') {
f686d7
+	    restore_queue_signals(q);
f686d7
 	    if (c == '\n')
f686d7
 		*p++ = '\n';
f686d7
 	    if (p > buf) {
f686d7
@@ -163,11 +166,13 @@ shingetline(void)
f686d7
 	} else
f686d7
 	    *p++ = c;
f686d7
 	if (p >= buf + BUFSIZ - 1) {
f686d7
+	    queue_signals();
f686d7
 	    line = zrealloc(line, ll + (p - buf) + 1);
f686d7
 	    memcpy(line + ll, buf, p - buf);
f686d7
 	    ll += p - buf;
f686d7
 	    line[ll] = '\0';
f686d7
 	    p = buf;
f686d7
+	    unqueue_signals();
f686d7
 	}
f686d7
     }
f686d7
 }
f686d7
@@ -340,6 +345,8 @@ inputline(void)
f686d7
 static void
f686d7
 inputsetline(char *str, int flags)
f686d7
 {
f686d7
+    queue_signals();
f686d7
+
f686d7
     if ((inbufflags & INP_FREE) && inbuf) {
f686d7
 	free(inbuf);
f686d7
     }
f686d7
@@ -357,6 +364,8 @@ inputsetline(char *str, int flags)
f686d7
     else
f686d7
 	inbufct = inbufleft;
f686d7
     inbufflags = flags;
f686d7
+
f686d7
+    unqueue_signals();
f686d7
 }
f686d7
 
f686d7
 /*
f686d7
diff --git a/Src/loop.c b/Src/loop.c
f686d7
index 90a0761..0c07c73 100644
f686d7
--- a/Src/loop.c
f686d7
+++ b/Src/loop.c
f686d7
@@ -56,6 +56,10 @@ execfor(Estate state, int do_exec)
f686d7
     char *name, *str, *cond = NULL, *advance = NULL;
f686d7
     zlong val = 0;
f686d7
     LinkList vars = NULL, args = NULL;
f686d7
+    int old_simple_pline = simple_pline;
f686d7
+
f686d7
+    /* See comments in execwhile() */
f686d7
+    simple_pline = 1;
f686d7
 
f686d7
     end = state->pc + WC_FOR_SKIP(code);
f686d7
 
f686d7
@@ -73,6 +77,7 @@ execfor(Estate state, int do_exec)
f686d7
 	    matheval(str);
f686d7
 	if (errflag) {
f686d7
 	    state->pc = end;
f686d7
+	    simple_pline = old_simple_pline;
f686d7
 	    return lastval = errflag;
f686d7
 	}
f686d7
 	cond = ecgetstr(state, EC_NODUP, &ctok);
f686d7
@@ -85,6 +90,7 @@ execfor(Estate state, int do_exec)
f686d7
 
f686d7
 	    if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
f686d7
 		state->pc = end;
f686d7
+		simple_pline = old_simple_pline;
f686d7
 		return 0;
f686d7
 	    }
f686d7
 	    if (htok)
f686d7
@@ -190,6 +196,7 @@ execfor(Estate state, int do_exec)
f686d7
     popheap();
f686d7
     cmdpop();
f686d7
     loops--;
f686d7
+    simple_pline = old_simple_pline;
f686d7
     state->pc = end;
f686d7
     return lastval;
f686d7
 }
f686d7
@@ -206,6 +213,10 @@ execselect(Estate state, UNUSED(int do_exec))
f686d7
     FILE *inp;
f686d7
     size_t more;
f686d7
     LinkList args;
f686d7
+    int old_simple_pline = simple_pline;
f686d7
+
f686d7
+    /* See comments in execwhile() */
f686d7
+    simple_pline = 1;
f686d7
 
f686d7
     end = state->pc + WC_FOR_SKIP(code);
f686d7
     name = ecgetstr(state, EC_NODUP, NULL);
f686d7
@@ -221,6 +232,7 @@ execselect(Estate state, UNUSED(int do_exec))
f686d7
 
f686d7
 	if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
f686d7
 	    state->pc = end;
f686d7
+	    simple_pline = old_simple_pline;
f686d7
 	    return 0;
f686d7
 	}
f686d7
 	if (htok)
f686d7
@@ -228,6 +240,7 @@ execselect(Estate state, UNUSED(int do_exec))
f686d7
     }
f686d7
     if (!args || empty(args)) {
f686d7
 	state->pc = end;
f686d7
+	simple_pline = old_simple_pline;
f686d7
 	return 1;
f686d7
     }
f686d7
     loops++;
f686d7
@@ -301,6 +314,7 @@ execselect(Estate state, UNUSED(int do_exec))
f686d7
     popheap();
f686d7
     fclose(inp);
f686d7
     loops--;
f686d7
+    simple_pline = old_simple_pline;
f686d7
     state->pc = end;
f686d7
     return lastval;
f686d7
 }
f686d7
@@ -368,6 +382,7 @@ execwhile(Estate state, UNUSED(int do_exec))
f686d7
     Wordcode end, loop;
f686d7
     wordcode code = state->pc[-1];
f686d7
     int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
f686d7
+    int old_simple_pline = simple_pline;
f686d7
 
f686d7
     end = state->pc + WC_WHILE_SKIP(code);
f686d7
     olderrexit = noerrexit;
f686d7
@@ -382,8 +397,6 @@ execwhile(Estate state, UNUSED(int do_exec))
f686d7
         /* This is an empty loop.  Make sure the signal handler sets the
f686d7
         * flags and then just wait for someone hitting ^C. */
f686d7
 
f686d7
-        int old_simple_pline = simple_pline;
f686d7
-
f686d7
         simple_pline = 1;
f686d7
 
f686d7
         while (!breaks)
f686d7
@@ -395,7 +408,14 @@ execwhile(Estate state, UNUSED(int do_exec))
f686d7
         for (;;) {
f686d7
             state->pc = loop;
f686d7
             noerrexit = 1;
f686d7
+
f686d7
+	    /* In case the test condition is a functional no-op,
f686d7
+	     * make sure signal handlers recognize ^C to end the loop. */
f686d7
+	    simple_pline = 1;
f686d7
+
f686d7
             execlist(state, 1, 0);
f686d7
+
f686d7
+	    simple_pline = old_simple_pline;
f686d7
             noerrexit = olderrexit;
f686d7
             if (!((lastval == 0) ^ isuntil)) {
f686d7
                 if (breaks)
f686d7
@@ -407,7 +427,14 @@ execwhile(Estate state, UNUSED(int do_exec))
f686d7
                 lastval = oldval;
f686d7
                 break;
f686d7
             }
f686d7
+
f686d7
+	    /* In case the loop body is also a functional no-op,
f686d7
+	     * make sure signal handlers recognize ^C as above. */
f686d7
+	    simple_pline = 1;
f686d7
+
f686d7
             execlist(state, 1, 0);
f686d7
+
f686d7
+	    simple_pline = old_simple_pline;
f686d7
             if (breaks) {
f686d7
                 breaks--;
f686d7
                 if (breaks || !contflag)
f686d7
@@ -438,6 +465,10 @@ execrepeat(Estate state, UNUSED(int do_exec))
f686d7
     wordcode code = state->pc[-1];
f686d7
     int count, htok = 0;
f686d7
     char *tmp;
f686d7
+    int old_simple_pline = simple_pline;
f686d7
+
f686d7
+    /* See comments in execwhile() */
f686d7
+    simple_pline = 1;
f686d7
 
f686d7
     end = state->pc + WC_REPEAT_SKIP(code);
f686d7
 
f686d7
@@ -470,6 +501,7 @@ execrepeat(Estate state, UNUSED(int do_exec))
f686d7
     cmdpop();
f686d7
     popheap();
f686d7
     loops--;
f686d7
+    simple_pline = old_simple_pline;
f686d7
     state->pc = end;
f686d7
     return lastval;
f686d7
 }
f686d7
diff --git a/Src/parse.c b/Src/parse.c
f686d7
index b0a7624..04d2707 100644
f686d7
--- a/Src/parse.c
f686d7
+++ b/Src/parse.c
f686d7
@@ -379,6 +379,8 @@ init_parse_status(void)
f686d7
 void
f686d7
 init_parse(void)
f686d7
 {
f686d7
+    queue_signals();
f686d7
+
f686d7
     if (ecbuf) zfree(ecbuf, eclen);
f686d7
 
f686d7
     ecbuf = (Wordcode) zalloc((eclen = EC_INIT_SIZE) * sizeof(wordcode));
f686d7
@@ -389,6 +391,8 @@ init_parse(void)
f686d7
     ecnfunc = 0;
f686d7
 
f686d7
     init_parse_status();
f686d7
+
f686d7
+    unqueue_signals();
f686d7
 }
f686d7
 
f686d7
 /* Build eprog. */
f686d7
@@ -409,6 +413,8 @@ bld_eprog(void)
f686d7
     Eprog ret;
f686d7
     int l;
f686d7
 
f686d7
+    queue_signals();
f686d7
+
f686d7
     ecadd(WCB_END());
f686d7
 
f686d7
     ret = (Eprog) zhalloc(sizeof(*ret));
f686d7
@@ -431,6 +437,8 @@ bld_eprog(void)
f686d7
     zfree(ecbuf, eclen);
f686d7
     ecbuf = NULL;
f686d7
 
f686d7
+    unqueue_signals();
f686d7
+
f686d7
     return ret;
f686d7
 }
f686d7
 
f686d7
diff --git a/Src/signals.c b/Src/signals.c
f686d7
index c539063..73b41b1 100644
f686d7
--- a/Src/signals.c
f686d7
+++ b/Src/signals.c
f686d7
@@ -1194,6 +1194,8 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
f686d7
 	}
f686d7
     }
f686d7
 
f686d7
+    queue_signals();	/* Any time we manage memory or global state */
f686d7
+
f686d7
     intrap++;
f686d7
     *sigtr |= ZSIG_IGNORED;
f686d7
 
f686d7
@@ -1231,7 +1233,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
f686d7
 
f686d7
 	sfcontext = SFC_SIGNAL;
f686d7
 	incompfunc = 0;
f686d7
-	doshfunc((Shfunc)sigfn, args, 1);
f686d7
+	doshfunc((Shfunc)sigfn, args, 1);	/* manages signal queueing */
f686d7
 	sfcontext = osc;
f686d7
 	incompfunc= old_incompfunc;
f686d7
 	freelinklist(args, (FreeFunc) NULL);
f686d7
@@ -1241,7 +1243,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
f686d7
 	trap_state = TRAP_STATE_PRIMED;
f686d7
 	trapisfunc = isfunc = 0;
f686d7
 
f686d7
-	execode((Eprog)sigfn, 1, 0, "trap");
f686d7
+	execode((Eprog)sigfn, 1, 0, "trap");	/* manages signal queueing */
f686d7
     }
f686d7
     runhookdef(AFTERTRAPHOOK, NULL);
f686d7
 
f686d7
@@ -1286,6 +1288,8 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
f686d7
     if (*sigtr != ZSIG_IGNORED)
f686d7
 	*sigtr &= ~ZSIG_IGNORED;
f686d7
     intrap--;
f686d7
+
f686d7
+    unqueue_signals();
f686d7
 }
f686d7
 
f686d7
 /* Standard call to execute a trap for a given signal. */
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From 33905958a1b94e83ca1c32bc6849906da94b91a6 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Sun, 9 Aug 2015 17:37:23 -0700
f686d7
Subject: [PATCH 3/8] 36033: a few more queue_signals() to protect global state
f686d7
 changes
f686d7
f686d7
Upstream-commit: df5f825538720a9422859200d58d075d1dd075fc
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/glob.c    | 4 ++++
f686d7
 Src/pattern.c | 8 +++++++-
f686d7
 2 files changed, 11 insertions(+), 1 deletion(-)
f686d7
f686d7
diff --git a/Src/glob.c b/Src/glob.c
f686d7
index ca2ffaf..9135fce 100644
f686d7
--- a/Src/glob.c
f686d7
+++ b/Src/glob.c
f686d7
@@ -213,22 +213,26 @@ static struct globdata curglobdata;
f686d7
 
f686d7
 #define save_globstate(N) \
f686d7
   do { \
f686d7
+    queue_signals(); \
f686d7
     memcpy(&(N), &curglobdata, sizeof(struct globdata)); \
f686d7
     (N).gd_pathpos = pathpos; \
f686d7
     (N).gd_pathbuf = pathbuf; \
f686d7
     (N).gd_glob_pre = glob_pre; \
f686d7
     (N).gd_glob_suf = glob_suf; \
f686d7
     pathbuf = NULL; \
f686d7
+    unqueue_signals(); \
f686d7
   } while (0)
f686d7
 
f686d7
 #define restore_globstate(N) \
f686d7
   do { \
f686d7
+    queue_signals(); \
f686d7
     zfree(pathbuf, pathbufsz); \
f686d7
     memcpy(&curglobdata, &(N), sizeof(struct globdata)); \
f686d7
     pathpos = (N).gd_pathpos; \
f686d7
     pathbuf = (N).gd_pathbuf; \
f686d7
     glob_pre = (N).gd_glob_pre; \
f686d7
     glob_suf = (N).gd_glob_suf; \
f686d7
+    unqueue_signals(); \
f686d7
   } while (0)
f686d7
 
f686d7
 /* pathname component in filename patterns */
f686d7
diff --git a/Src/pattern.c b/Src/pattern.c
f686d7
index b74a08a..52774c0 100644
f686d7
--- a/Src/pattern.c
f686d7
+++ b/Src/pattern.c
f686d7
@@ -452,6 +452,8 @@ patcompile(char *exp, int inflags, char **endexp)
f686d7
     char *lng, *strp = NULL;
f686d7
     Patprog p;
f686d7
 
f686d7
+    queue_signals();
f686d7
+
f686d7
     startoff = sizeof(struct patprog);
f686d7
     /* Ensure alignment of start of program string */
f686d7
     startoff = (startoff + sizeof(union upat) - 1) & ~(sizeof(union upat) - 1);
f686d7
@@ -521,8 +523,10 @@ patcompile(char *exp, int inflags, char **endexp)
f686d7
 	if (!strp || (*strp && *strp != '/')) {
f686d7
 	    /* No, do normal compilation. */
f686d7
 	    strp = NULL;
f686d7
-	    if (patcompswitch(0, &flags) == 0)
f686d7
+	    if (patcompswitch(0, &flags) == 0) {
f686d7
+		unqueue_signals();
f686d7
 		return NULL;
f686d7
+	    }
f686d7
 	} else {
f686d7
 	    /*
f686d7
 	     * Yes, copy the string, and skip compilation altogether.
f686d7
@@ -654,6 +658,8 @@ patcompile(char *exp, int inflags, char **endexp)
f686d7
 
f686d7
     if (endexp)
f686d7
 	*endexp = patparse;
f686d7
+
f686d7
+    unqueue_signals();
f686d7
     return p;
f686d7
 }
f686d7
 
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From bba38460c88c36fb529ee7494570cb2cfc68641a Mon Sep 17 00:00:00 2001
f686d7
From: Peter Stephenson <pws@zsh.org>
f686d7
Date: Mon, 10 Aug 2015 16:59:55 +0100
f686d7
Subject: [PATCH 4/8] Don't rely on implicit value when saving background
f686d7
 process status
f686d7
f686d7
Upstream-commit: a07f74fadd1180b42258d1fcec5359afe3f9ba00
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/signals.c | 9 ++++++++-
f686d7
 1 file changed, 8 insertions(+), 1 deletion(-)
f686d7
f686d7
diff --git a/Src/signals.c b/Src/signals.c
f686d7
index 73b41b1..2e7304f 100644
f686d7
--- a/Src/signals.c
f686d7
+++ b/Src/signals.c
f686d7
@@ -533,7 +533,14 @@ wait_for_processes(void)
f686d7
 	 */
f686d7
 	if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) &&
f686d7
 	    jn - jobtab != thisjob)
f686d7
-	    addbgstatus(pid, (int)lastval2);
f686d7
+	{
f686d7
+	    int val = (WIFSIGNALED(status) ?
f686d7
+		   0200 | WTERMSIG(status) :
f686d7
+		   (WIFSTOPPED(status) ?
f686d7
+		    0200 | WEXITSTATUS(status) :
f686d7
+		    WEXITSTATUS(status)));
f686d7
+	    addbgstatus(pid, val);
f686d7
+	}
f686d7
 
f686d7
 	unqueue_signals();
f686d7
     }
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From 530b59d58273c9f11cd1443c0865f6420eafcbf0 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Tue, 11 Aug 2015 08:44:15 -0700
f686d7
Subject: [PATCH 5/8] 36090: keep signals queued for preprompt()
f686d7
f686d7
Upstream-commit: 1af2e6e02d5cb8ca8d11f107b670cddfd10a7e81
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/init.c | 2 --
f686d7
 1 file changed, 2 deletions(-)
f686d7
f686d7
diff --git a/Src/init.c b/Src/init.c
f686d7
index df42349..ca616d3 100644
f686d7
--- a/Src/init.c
f686d7
+++ b/Src/init.c
f686d7
@@ -119,9 +119,7 @@ loop(int toplevel, int justonce)
f686d7
 	    if (interact && toplevel) {
f686d7
 	        int hstop = stophist;
f686d7
 		stophist = 3;
f686d7
-		unqueue_signals();
f686d7
 		preprompt();
f686d7
-		queue_signals();
f686d7
 		if (stophist != 3)
f686d7
 		    hbegin(1);
f686d7
 		else
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From b2994c9f3ef36c3ee3286a08736da1e2c8d65f0b Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Tue, 11 Aug 2015 08:53:12 -0700
f686d7
Subject: [PATCH 6/8] 36104: change order of child_block() and
f686d7
 dont_queue_signals() to resolve yet another race condition
f686d7
f686d7
Upstream-commit: 128bf385b1e8256e412d732fa9b80ecd7c5e2c73
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/exec.c | 2 +-
f686d7
 Src/jobs.c | 4 ++--
f686d7
 2 files changed, 3 insertions(+), 3 deletions(-)
f686d7
f686d7
diff --git a/Src/exec.c b/Src/exec.c
f686d7
index cff1a24..70e2279 100644
f686d7
--- a/Src/exec.c
f686d7
+++ b/Src/exec.c
f686d7
@@ -1570,8 +1570,8 @@ execpline(Estate state, wordcode slcode, int how, int last1)
f686d7
 		    !(jobtab[list_pipe_job].stat & STAT_STOPPED)) {
f686d7
 		    int q = queue_signal_level();
f686d7
 		    child_unblock();
f686d7
-		    dont_queue_signals();
f686d7
 		    child_block();
f686d7
+		    dont_queue_signals();
f686d7
 		    restore_queue_signals(q);
f686d7
 		}
f686d7
 		if (list_pipe_child &&
f686d7
diff --git a/Src/jobs.c b/Src/jobs.c
f686d7
index 24b8494..e711a9b 100644
f686d7
--- a/Src/jobs.c
f686d7
+++ b/Src/jobs.c
f686d7
@@ -1312,9 +1312,9 @@ zwaitjob(int job, int wait_cmd)
f686d7
     int q = queue_signal_level();
f686d7
     Job jn = jobtab + job;
f686d7
 
f686d7
-    dont_queue_signals();
f686d7
     child_block();		 /* unblocked during signal_suspend() */
f686d7
     queue_traps(wait_cmd);
f686d7
+    dont_queue_signals();
f686d7
     if (jn->procs || jn->auxprocs) { /* if any forks were done         */
f686d7
 	jn->stat |= STAT_LOCKED;
f686d7
 	if (jn->stat & STAT_CHANGED)
f686d7
@@ -1350,9 +1350,9 @@ zwaitjob(int job, int wait_cmd)
f686d7
 	pipestats[0] = lastval;
f686d7
 	numpipestats = 1;
f686d7
     }
f686d7
+    restore_queue_signals(q);
f686d7
     unqueue_traps();
f686d7
     child_unblock();
f686d7
-    restore_queue_signals(q);
f686d7
 
f686d7
     return 0;
f686d7
 }
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From 6a0fd02f08972875cc138e783e28515a5c7a7e04 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Sat, 15 Aug 2015 10:15:30 -0700
f686d7
Subject: [PATCH 7/8] 36180: avoid infinite job stop/continue loop on "wait
f686d7
 PID" for a background job
f686d7
f686d7
Upstream-commit: 5d019f426af8b2a600ee03e43782c24b357d1401
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/jobs.c | 9 ++++++++-
f686d7
 1 file changed, 8 insertions(+), 1 deletion(-)
f686d7
f686d7
diff --git a/Src/jobs.c b/Src/jobs.c
f686d7
index e711a9b..9b94a1f 100644
f686d7
--- a/Src/jobs.c
f686d7
+++ b/Src/jobs.c
f686d7
@@ -1276,10 +1276,17 @@ waitforpid(pid_t pid, int wait_cmd)
f686d7
     dont_queue_signals();
f686d7
     child_block();		/* unblocked in signal_suspend() */
f686d7
     queue_traps(wait_cmd);
f686d7
+
f686d7
+    /* This function should never be called with a pid that is not a
f686d7
+     * child of the current shell.  Consequently, if kill(0, pid)
f686d7
+     * fails here with ESRCH, the child has already been reaped.  In
f686d7
+     * the loop body, we expect this to happen in signal_suspend()
f686d7
+     * via zhandler(), after which this test terminates the loop.
f686d7
+     */
f686d7
     while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
f686d7
 	if (first)
f686d7
 	    first = 0;
f686d7
-	else
f686d7
+	else if (!wait_cmd)
f686d7
 	    kill(pid, SIGCONT);
f686d7
 
f686d7
 	last_signal = -1;
f686d7
-- 
f686d7
2.5.0
f686d7
f686d7
f686d7
From d184dd8673c93d35855b4a04613ae09277214df5 Mon Sep 17 00:00:00 2001
f686d7
From: "Barton E. Schaefer" <schaefer@zsh.org>
f686d7
Date: Wed, 2 Sep 2015 19:11:54 -0700
f686d7
Subject: [PATCH 8/8] 36393: process queued signals during dotrap()
f686d7
f686d7
Upstream-commit: 9f5dffa1f33ec43c306bdf3c87cebba5fcc95b64
f686d7
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f686d7
---
f686d7
 Src/signals.c          | 5 +++++
f686d7
 Test/A05execution.ztst | 9 +++++++++
f686d7
 2 files changed, 14 insertions(+)
f686d7
f686d7
diff --git a/Src/signals.c b/Src/signals.c
f686d7
index 2e7304f..dbc84af 100644
f686d7
--- a/Src/signals.c
f686d7
+++ b/Src/signals.c
f686d7
@@ -1306,6 +1306,7 @@ void
f686d7
 dotrap(int sig)
f686d7
 {
f686d7
     void *funcprog;
f686d7
+    int q = queue_signal_level();
f686d7
 
f686d7
     if (sigtrapped[sig] & ZSIG_FUNC) {
f686d7
 	HashNode hn = gettrapnode(sig, 0);
f686d7
@@ -1328,5 +1329,9 @@ dotrap(int sig)
f686d7
     if ((sigtrapped[sig] & ZSIG_IGNORED) || !funcprog || errflag)
f686d7
 	return;
f686d7
 
f686d7
+    dont_queue_signals();
f686d7
+
f686d7
     dotrapargs(sig, sigtrapped+sig, funcprog);
f686d7
+
f686d7
+    restore_queue_signals(q);
f686d7
 }
f686d7
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
f686d7
index 77c569c..3b39c75 100644
f686d7
--- a/Test/A05execution.ztst
f686d7
+++ b/Test/A05execution.ztst
f686d7
@@ -203,3 +203,12 @@
f686d7
 1:The status of recently exited background jobs is recorded
f686d7
 >3
f686d7
 >2
f686d7
+
f686d7
+# Regression test for workers/36392
f686d7
+  print -u $ZTST_fd 'This test takes 3 seconds and hangs the shell when it fails...'
f686d7
+  callfromchld() { true && { print CHLD } }
f686d7
+  TRAPCHLD() { callfromchld }
f686d7
+  sleep 2 & sleep 3; print OK
f686d7
+0:Background job exit does not affect reaping foreground job
f686d7
+>CHLD
f686d7
+>OK
f686d7
-- 
f686d7
2.5.0
f686d7