summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2016-12-05 11:21:01 +0000
committerPeter Stephenson <pws@zsh.org>2016-12-05 11:21:01 +0000
commitc03228f9ed28dfaa9ded49eabb93c04def5ac547 (patch)
tree7ea3ee905bf9531dce1e4e46b206ac9eb438d566
parentf71de84f1d9f7c2d63226a2e5534fc12d05ec716 (diff)
downloadzsh-c03228f9ed28dfaa9ded49eabb93c04def5ac547.tar.gz
zsh-c03228f9ed28dfaa9ded49eabb93c04def5ac547.zip
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.
-rw-r--r--ChangeLog6
-rw-r--r--Src/exec.c10
-rw-r--r--Src/loop.c6
-rw-r--r--Src/zsh.h1
-rw-r--r--Test/C03traps.ztst70
5 files changed, 92 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 67f8c7687..c0afd0773 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2016-12-05 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 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 <d.s@daniel.shahaf.name>
* 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