From c03228f9ed28dfaa9ded49eabb93c04def5ac547 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 5 Dec 2016 11:21:01 +0000 Subject: Extra case for ERR_RETURN and ERR_EXIT. Don't trigger just because status is non-zero at end of complex shell construct as this may be a case we've already suppressed. --- ChangeLog | 6 +++++ Src/exec.c | 10 +++++++- Src/loop.c | 6 +++++ Src/zsh.h | 1 + Test/C03traps.ztst | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 67f8c7687..c0afd0773 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2016-12-05 Peter Stephenson + + * 40096: Src/exec.c, Src/loop.c, Src/zsh.h, Test/C03traps.ztst: + Don't trigger ERR_EXIT or ERR_RETURN on non-zero status after + shell construct. + 2016-12-04 Daniel Shahaf * unposted: Functions/VCS_Info/Backends/VCS_INFO_get_data_git: diff --git a/Src/exec.c b/Src/exec.c index f544a33e7..6e197ddf2 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -46,6 +46,11 @@ enum { /**/ int noerrexit; +/* used to suppress ERREXIT for one occurrence */ + +/**/ +int this_noerrexit; + /* * noerrs = 1: suppress error messages * noerrs = 2: don't set errflag on parse error, either @@ -1238,7 +1243,8 @@ execlist(Estate state, int dont_change_job, int exiting) } while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) { int donedebug; - int this_noerrexit = 0, this_donetrap = 0; + int this_donetrap = 0; + this_noerrexit = 0; ltype = WC_LIST_TYPE(code); csp = cmdsp; @@ -5813,6 +5819,7 @@ execsave(void) es->trapisfunc = trapisfunc; es->traplocallevel = traplocallevel; es->noerrs = noerrs; + es->this_noerrexit = this_noerrexit; es->underscore = ztrdup(zunderscore); es->next = exstack; exstack = es; @@ -5847,6 +5854,7 @@ execrestore(void) trapisfunc = en->trapisfunc; traplocallevel = en->traplocallevel; noerrs = en->noerrs; + this_noerrexit = en->this_noerrexit; setunderscore(en->underscore); zsfree(en->underscore); free(en); diff --git a/Src/loop.c b/Src/loop.c index 367c0df5c..ae87b2f5f 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -208,6 +208,7 @@ execfor(Estate state, int do_exec) loops--; simple_pline = old_simple_pline; state->pc = end; + this_noerrexit = 1; return lastval; } @@ -335,6 +336,7 @@ execselect(Estate state, UNUSED(int do_exec)) loops--; simple_pline = old_simple_pline; state->pc = end; + this_noerrexit = 1; return lastval; } @@ -472,6 +474,7 @@ execwhile(Estate state, UNUSED(int do_exec)) popheap(); loops--; state->pc = end; + this_noerrexit = 1; return lastval; } @@ -523,6 +526,7 @@ execrepeat(Estate state, UNUSED(int do_exec)) loops--; simple_pline = old_simple_pline; state->pc = end; + this_noerrexit = 1; return lastval; } @@ -573,6 +577,7 @@ execif(Estate state, int do_exec) lastval = 0; } state->pc = end; + this_noerrexit = 1; return lastval; } @@ -682,6 +687,7 @@ execcase(Estate state, int do_exec) if (!anypatok) lastval = 0; + this_noerrexit = 1; return lastval; } diff --git a/Src/zsh.h b/Src/zsh.h index dae2b2459..f2c030004 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1070,6 +1070,7 @@ struct execstack { int trapisfunc; int traplocallevel; int noerrs; + int this_noerrexit; char *underscore; }; diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst index c3bedb06c..e94fb6f85 100644 --- a/Test/C03traps.ztst +++ b/Test/C03traps.ztst @@ -626,6 +626,76 @@ F:Must be tested with a top-level script rather than source or function >before-out >before-in + (setopt err_exit + for x in y; do + false && true + done + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of for +>OK + + (setopt err_exit + integer x=0 + while (( ! x++ )); do + false && true + done + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of while +>OK + + (setopt err_exit + repeat 1; do + false && true + done + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of repeat +>OK + + (setopt err_exit + if true; then + false && true + fi + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of if +>OK + + (setopt err_exit + for x in y; do + false + done + print OK + ) +1:ERR_EXIT triggered by status 1 within for + + (setopt err_exit + integer x=0 + while (( ! x++ )); do + false + done + print OK + ) +1:ERR_EXIT triggered by status 1 within while + + (setopt err_exit + repeat 1; do + false + done + print OK + ) +1:ERR_EXIT triggered by status 1 within repeat + + (setopt err_exit + if true; then + false + fi + print OK + ) +1:ERR_EXIT triggered by status 1 within if + if zmodload zsh/system 2>/dev/null; then ( trap 'echo TERM; exit 2' TERM -- cgit 1.4.1