mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-05-31 12:26:03 +02:00
41012: Fix premature exit from nested function in EXIT trap.
Also add check so we don't delay an exit if we were already in an EXIT trap for the main shell, as we should in that case leave immediately.
This commit is contained in:
parent
48b0daf3d4
commit
d7110d8f01
|
@ -1,3 +1,11 @@
|
|||
2017-04-27 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* 41012: Src/builtin.c, Src/exec.c, Src/signals.c,
|
||||
Test/C03traps.ztst: Fix early exit from nested functions in EXIT
|
||||
trap. Drive-by fix of testing for need to exit if exiting when
|
||||
already in EXIT trap for main shell --- we should just leave
|
||||
immediately.
|
||||
|
||||
2017-04-27 Peter Stephenson <p.stephenson@samsung.com>
|
||||
|
||||
* 41016: Test/A01grammar.ztst: test that quoted precommand
|
||||
|
|
|
@ -5500,7 +5500,7 @@ bin_break(char *name, char **argv, UNUSED(Options ops), int func)
|
|||
}
|
||||
/*FALLTHROUGH*/
|
||||
case BIN_EXIT:
|
||||
if (locallevel > forklevel) {
|
||||
if (locallevel > forklevel && shell_exiting != -1) {
|
||||
/*
|
||||
* We don't exit directly from functions to allow tidying
|
||||
* up, in particular EXIT traps. We still need to perform
|
||||
|
@ -5509,6 +5509,9 @@ bin_break(char *name, char **argv, UNUSED(Options ops), int func)
|
|||
*
|
||||
* If we are forked, we exit the shell at the function depth
|
||||
* at which we became a subshell, hence the comparison.
|
||||
*
|
||||
* If we are already exiting... give this all up as
|
||||
* a bad job.
|
||||
*/
|
||||
if (stopmsg || (zexit(0,2), !stopmsg)) {
|
||||
retflag = 1;
|
||||
|
@ -5555,6 +5558,14 @@ checkjobs(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* -1 if the shell is already committed to exit.
|
||||
* positive if zexit() was already called.
|
||||
*/
|
||||
|
||||
/**/
|
||||
int shell_exiting;
|
||||
|
||||
/* exit the shell. val is the return value of the shell. *
|
||||
* from_where is
|
||||
* 1 if zexit is called because of a signal
|
||||
|
@ -5566,10 +5577,8 @@ checkjobs(void)
|
|||
mod_export void
|
||||
zexit(int val, int from_where)
|
||||
{
|
||||
static int in_exit;
|
||||
|
||||
/* Don't do anything recursively: see below */
|
||||
if (in_exit == -1)
|
||||
if (shell_exiting == -1)
|
||||
return;
|
||||
|
||||
if (isset(MONITOR) && !stopmsg && from_where != 1) {
|
||||
|
@ -5582,14 +5591,14 @@ zexit(int val, int from_where)
|
|||
}
|
||||
}
|
||||
/* Positive in_exit means we have been here before */
|
||||
if (from_where == 2 || (in_exit++ && from_where))
|
||||
if (from_where == 2 || (shell_exiting++ && from_where))
|
||||
return;
|
||||
|
||||
/*
|
||||
* We're now committed to exiting. Set in_exit to -1 to
|
||||
* We're now committed to exiting. Set shell_exiting to -1 to
|
||||
* indicate we shouldn't do any recursive processing.
|
||||
*/
|
||||
in_exit = -1;
|
||||
shell_exiting = -1;
|
||||
/*
|
||||
* We want to do all remaining processing regardless of preceding
|
||||
* errors, even user interrupts.
|
||||
|
|
|
@ -5688,8 +5688,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
|
|||
* the only likely case where we need that second test is
|
||||
* when we have an "always" block. The endparamscope() has
|
||||
* already happened, hence the "+1" here.
|
||||
*
|
||||
* If we are in an exit trap, finish it first... we wouldn't set
|
||||
* exit_pending if we were already in one.
|
||||
*/
|
||||
if (exit_pending && exit_level >= locallevel+1) {
|
||||
if (exit_pending && exit_level >= locallevel+1 && !in_exit_trap) {
|
||||
if (locallevel > forklevel) {
|
||||
/* Still functions to return: force them to do so. */
|
||||
retflag = 1;
|
||||
|
|
|
@ -55,6 +55,11 @@ mod_export Eprog siglists[VSIGCOUNT];
|
|||
/**/
|
||||
mod_export int nsigtrapped;
|
||||
|
||||
/* Running an exit trap? */
|
||||
|
||||
/**/
|
||||
int in_exit_trap;
|
||||
|
||||
/*
|
||||
* Flag that exit trap has been set in POSIX mode.
|
||||
* The setter's expectation is therefore that it is run
|
||||
|
@ -1435,7 +1440,13 @@ dotrap(int sig)
|
|||
|
||||
dont_queue_signals();
|
||||
|
||||
if (sig == SIGEXIT)
|
||||
++in_exit_trap;
|
||||
|
||||
dotrapargs(sig, sigtrapped+sig, funcprog);
|
||||
|
||||
if (sig == SIGEXIT)
|
||||
--in_exit_trap;
|
||||
|
||||
restore_queue_signals(q);
|
||||
}
|
||||
|
|
|
@ -756,6 +756,27 @@ F:Must be tested with a top-level script rather than source or function
|
|||
>''
|
||||
>hello
|
||||
|
||||
$ZTST_testdir/../Src/zsh -f =(<<<"
|
||||
trap handler EXIT
|
||||
handler() {
|
||||
echoa
|
||||
echo b
|
||||
}
|
||||
echoa() {
|
||||
echo a
|
||||
}
|
||||
exit0() {
|
||||
exit
|
||||
}
|
||||
main() {
|
||||
exit0
|
||||
}
|
||||
main
|
||||
")
|
||||
0:No early exit from nested function in EXIT trap.
|
||||
>a
|
||||
>b
|
||||
|
||||
%clean
|
||||
|
||||
rm -f TRAPEXIT
|
||||
|
|
Loading…
Reference in New Issue