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

Re: set -e bug



On Thu, 13 Dec 2012 00:54:23 +0100
Vincent Lefevre <vincent@xxxxxxxxxx> wrote:
> I think I've found a "set -e" bug, which I can reproduce in zsh 4.3.17
> (Debian/unstable) and zsh 5.0.0 (Ubuntu). Consider the following zsh
> script:
> 
> ----------------------------------------
> #!/usr/bin/env zsh
> 
> set -e
> echo $ZSH_VERSION
> printf "a\nb\n" | while read line
> do
>   [[ $line = a* ]] || continue
>   #echo "$line"
>   ((ctr++))
>   [[ $line = foo ]]
> done
> echo "ctr = $ctr"
> ----------------------------------------
> 
> I get:
> 
> 4.3.17
> ctr = 1
> 
> with an exit status 0, even though [[ $line = foo ]] is false.

This is still there (it's not the same as the problem that we "exited"
on errors only to the top level of a script).

The logic to do with donetrap and noerrexit in execlist() has me stumped
at that moment --- it's not clear what the combined effect is supposed
to be, we seem to reset things before we use them, and some effects are
propagating up from nested calls --- but I'm reasonably confident that
resetting donetrap earlier is the right thing to do: it's done for all
normal executions of commands in a list, it should also be done when we
optimise the list to a single simple command, which is logically
equivalent to an end of list.

Indeed, this picks up a bug in another test where the wrong name of a
variable was used (and the variable must be set somewhere else, though I
didn't confirm this).  Somehow the return status of the test wasn't
being propagated so we never noticed.

Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.214
diff -p -u -r1.214 exec.c
--- Src/exec.c	11 Oct 2012 20:14:03 -0000	1.214
+++ Src/exec.c	13 Dec 2012 10:14:06 -0000
@@ -1207,6 +1207,9 @@ execlist(Estate state, int dont_change_j
 	} else
 	    donedebug = intrap ? 1 : 0;
 
+	/* Reset donetrap:  this ensures that a trap is only *
+	 * called once for each sublist that fails.          */
+	donetrap = 0;
 	if (ltype & Z_SIMPLE) {
 	    next = state->pc + WC_LIST_SKIP(code);
 	    if (donedebug != 2)
@@ -1214,9 +1217,6 @@ execlist(Estate state, int dont_change_j
 	    state->pc = next;
 	    goto sublist_done;
 	}
-	/* Reset donetrap:  this ensures that a trap is only *
-	 * called once for each sublist that fails.          */
-	donetrap = 0;
 
 	/* Loop through code followed by &&, ||, or end of sublist. */
 	code = *state->pc++;
Index: Test/A06assign.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A06assign.ztst,v
retrieving revision 1.8
diff -p -u -r1.8 A06assign.ztst
--- Test/A06assign.ztst	21 Dec 2010 16:54:31 -0000	1.8
+++ Test/A06assign.ztst	13 Dec 2012 10:14:06 -0000
@@ -184,8 +184,8 @@
 
  typeset -A hash
  hash=(one 1)
- h+=string
- [[ $h[@] == string ]]
+ hash+=string
+ [[ $hash[@] == string ]]
 0:add scalar to association
 
 # tests of var+=(array)
Index: Test/C03traps.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/C03traps.ztst,v
retrieving revision 1.20
diff -p -u -r1.20 C03traps.ztst
--- Test/C03traps.ztst	12 Sep 2010 18:56:41 -0000	1.20
+++ Test/C03traps.ztst	13 Dec 2012 10:14:06 -0000
@@ -388,6 +388,17 @@
 >}
 >No, really exited
 
+   (set -e
+    printf "a\nb\n" | while read line
+    do
+       [[ $line = a* ]] || continue
+       ((ctr++))
+       [[ $line = foo ]]
+    done
+    echo "ctr = $ctr"
+   )
+1:ERREXIT in loop with simple commands
+
 %clean
 
   rm -f TRAPEXIT



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