summaryrefslogtreecommitdiff
path: root/Src/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/exec.c')
-rw-r--r--Src/exec.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/Src/exec.c b/Src/exec.c
index 7612d4303..a635c18ed 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1121,10 +1121,14 @@ execsimple(Estate state)
fflush(xtrerr);
}
lv = (errflag ? errflag : cmdoutval);
- } else if (code == WC_FUNCDEF) {
- lv = execfuncdef(state, NULL);
} else {
- lv = (execfuncs[code - WC_CURSH])(state, 0);
+ int q = queue_signal_level();
+ dont_queue_signals();
+ if (code == WC_FUNCDEF)
+ lv = execfuncdef(state, NULL);
+ else
+ lv = (execfuncs[code - WC_CURSH])(state, 0);
+ restore_queue_signals(q);
}
thisjob = otj;
@@ -1158,6 +1162,8 @@ execlist(Estate state, int dont_change_job, int exiting)
*/
int oldnoerrexit = noerrexit;
+ queue_signals();
+
cj = thisjob;
old_pline_level = pline_level;
old_list_pipe = list_pipe;
@@ -1428,6 +1434,8 @@ sublist_done:
/* Make sure this doesn't get executed again. */
sigtrapped[SIGEXIT] = 0;
}
+
+ unqueue_signals();
}
/* Execute a pipeline. *
@@ -1456,6 +1464,14 @@ execpline(Estate state, wordcode slcode, int how, int last1)
else if (slflags & WC_SUBLIST_NOT)
last1 = 0;
+ /* If trap handlers are allowed to run here, they may start another
+ * external job in the middle of us starting this one, which can
+ * result in jobs being reaped before their job table entries have
+ * been initialized, which in turn leads to waiting forever for
+ * jobs that no longer exist. So don't do that.
+ */
+ queue_signals();
+
pj = thisjob;
ipipe[0] = ipipe[1] = opipe[0] = opipe[1] = 0;
child_block();
@@ -1468,6 +1484,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
*/
if ((thisjob = newjob = initjob()) == -1) {
child_unblock();
+ unqueue_signals();
return 1;
}
if (how & Z_TIMED)
@@ -1523,6 +1540,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
else
spawnjob();
child_unblock();
+ unqueue_signals();
/* Executing background code resets shell status */
return lastval = 0;
} else {
@@ -1580,15 +1598,18 @@ execpline(Estate state, wordcode slcode, int how, int last1)
}
if (!(jn->stat & STAT_LOCKED)) {
updated = hasprocs(thisjob);
- waitjobs();
+ waitjobs(); /* deals with signal queue */
child_block();
} else
updated = 0;
if (!updated &&
list_pipe_job && hasprocs(list_pipe_job) &&
!(jobtab[list_pipe_job].stat & STAT_STOPPED)) {
+ int q = queue_signal_level();
child_unblock();
+ dont_queue_signals();
child_block();
+ restore_queue_signals(q);
}
if (list_pipe_child &&
jn->stat & STAT_DONE &&
@@ -1672,6 +1693,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
break;
}
child_unblock();
+ unqueue_signals();
if (list_pipe && (lastval & 0200) && pj >= 0 &&
(!(jn->stat & STAT_INUSE) || (jn->stat & STAT_DONE))) {
@@ -3391,6 +3413,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
fflush(xtrerr);
}
} else if (isset(EXECOPT) && !errflag) {
+ int q = queue_signal_level();
/*
* We delay the entersubsh() to here when we are exec'ing
* the current shell (including a fake exec to run a builtin then
@@ -3431,11 +3454,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
} else
redir_prog = NULL;
+ dont_queue_signals();
lastval = execfuncdef(state, redir_prog);
+ restore_queue_signals(q);
}
else if (type >= WC_CURSH) {
if (last1 == 1)
do_exec = 1;
+ dont_queue_signals();
if (type == WC_AUTOFN) {
/*
* We pre-loaded this to get any redirs.
@@ -3444,6 +3470,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
lastval = execautofn_basic(state, do_exec);
} else
lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
+ restore_queue_signals(q);
} else if (is_builtin || is_shfunc) {
LinkList restorelist = 0, removelist = 0;
/* builtin or shell function */
@@ -3610,7 +3637,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
}
state->pc = opc;
}
+ dont_queue_signals();
lastval = execbuiltin(args, assigns, (Builtin) hn);
+ restore_queue_signals(q);
fflush(stdout);
if (save[1] == -2) {
if (ferror(stdout)) {
@@ -4820,11 +4849,9 @@ execshfunc(Shfunc shf, LinkList args)
if ((osfc = sfcontext) == SFC_NONE)
sfcontext = SFC_DIRECT;
xtrerr = stderr;
- unqueue_signals();
doshfunc(shf, args, 0);
- queue_signals();
sfcontext = osfc;
free(cmdstack);
cmdstack = ocs;
@@ -5039,6 +5066,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
static int funcdepth;
#endif
+ queue_signals(); /* Lots of memory and global state changes coming */
+
pushheap();
oargv0 = NULL;
@@ -5261,6 +5290,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
}
popheap();
+ unqueue_signals();
+
/*
* Exit with a tidy up.
* Only leave if we're at the end of the appropriate function ---
@@ -5299,6 +5330,8 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
int cont, ouu;
char *ou;
+ queue_signals();
+
ou = zalloc(ouu = underscoreused);
if (ou)
memcpy(ou, zunderscore, underscoreused);
@@ -5320,12 +5353,14 @@ runshfunc(Eprog prog, FuncWrap wrap, char *name)
wrap = wrap->next;
}
startparamscope();
- execode(prog, 1, 0, "shfunc");
+ execode(prog, 1, 0, "shfunc"); /* handles signal unqueueing */
if (ou) {
setunderscore(ou);
zfree(ou, ouu);
}
endparamscope();
+
+ unqueue_signals();
}
/* Search fpath for an undefined function. Finds the file, and returns the *