Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zsh 5.2-test-1



On Mon, 5 Dec 2016 10:42:28 +0000
Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> On Mon, 5 Dec 2016 10:28:02 +0100
> Vincent Lefevre <vincent@xxxxxxxxxx> wrote:
> > zira% echo $ZSH_VERSION
> > 5.2-test-1
> > zira% set -e; for i in a b; do echo $i; false && true; done; echo OK
> > a
> > b
> > zsh: exit 1     zsh -f
> 
> The special thing about this case appears to be that the status 1 is
> still in effect when we get to the "done".  So we exit at the end of the
> "for" loop.  We need to suppress evaluation of the status at that point
> by propagating the information up without breaking anything else, which
> is difficult.

This seems to be passing a healthy number of tests.

I've tended to test ERR_RETURN instead of ERR_EXIT as they have the same
set of problems and not causing the shell to exit is easier, but
actually this is all done in subshells anyway so might just as well test
ERR_EXIT to get some coverage for that, too.  But the tests aren't a
complete set --- some things are tested with one option, some the other.

pws

diff --git a/Src/exec.c b/Src/exec.c
index f544a33..6e197dd 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 367c0df..ae87b2f 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 dae2b245..f2c0300 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 c3bedb0..e94fb6f 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



Messages sorted by: Reverse Date, Date, Thread, Author