zsh-workers
 help / color / mirror / code / Atom feed
* Re: [PATCH] More ERR_EXIT (was Re: Tests RE behavior of ERR_EXIT)
@ 2022-11-12 22:16 Philippe Altherr
  2022-11-13  3:59 ` Philippe Altherr
  0 siblings, 1 reply; 28+ messages in thread
From: Philippe Altherr @ 2022-11-12 22:16 UTC (permalink / raw)
  To: Bart Schaefer, zsh-workers

[-- Attachment #1: Type: text/plain, Size: 5634 bytes --]

Hi Bart,

I just noticed the following change:

+Changes since 5.9
> +-----------------
> +
> +Handling of ERR_EXIT is corrected
> *when the final status of a structured+command* (for, select, while,
> repeat, if, case, or a list in braces)
> *is+nonzero*.  To be compatible with other shells, *"zsh -e" now exits* in
> +those circumstances, whereas previous versions did not.  This does not
> +affect the handling of nonzero status within conditional statements.


This looks wrong to me. It's not compatible with the third exception of POSiX
"set -e"
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set>
:

When this option is on, when any command fails (for any of the reasons
> listed in Consequences of Shell Errors or by returning an exit status
> greater than zero), the shell immediately shall exit, as if by executing
> the exit special built-in utility with no arguments, with the following
> exceptions:
>
>    1. The failure of any individual command in a multi-command pipeline
>    shall not cause the shell to exit. Only the failure of the pipeline itself
>    shall be considered.
>    2. The -e setting shall be ignored when executing the compound list
>    following the while, until, if, or elif reserved word, a pipeline beginning
>    with the ! reserved word, or any command of an AND-OR list other than the
>    last.
>    3. *If the exit status of a compound command other than a subshell
>    command was the result of a failure while -e was being ignored, then -e
>    shall not apply to this command.*
>
> My high-level understanding of exception 3 is that if an error was
produced by a condition (note that the last command in a sub-list is NOT a
condition but a regular command), then that error should bubble up the
evaluation stack, without triggering any ERR_EXIT, until it gets ignored
(for example on the left of a ";" in a sequence) or it becomes the result
of an enclosing function or subshell.

Let's consider the following example:

function foo() { if true; then false && true; fi }
> function bar() { foo }
> bar


Exception 2 tells us that "false && true" shouldn't trigger an ERR_EXIT. By
exception 3, the resulting exit status becomes the result, first of the
enclosing if, and then of the enclosing {}, without triggering an ERR_EXIT.
It's only in function "bar" that an "ERR_EXIT" should be triggered because
the call to "foo" returns 1 and function calls aren't compound commands.

Zsh 5.8.1, doesn't trigger any ERR_EXIT for this example. Zsh 5.9.*, with
your latest changes, triggers an ERR_EXIT in "foo". Bash 5.1.16 triggers an
ERR_EXIT in "bar". My understanding is that Bash is right.

Here is the script that I used to test this behavior with Zsh and Bash (for
bash you have to comment out the "foo?3" tests):

# test.zsh
> # Usage: test.zsh A1|...|A4|B1|...|B4|C1|...|C4
> #
> # Example: "test.zsh A1" runs the test for "fooA1".


> set -e


> function err-exit() {
>     local error=$?;
>     # Print where ERR_EXIT was called from.
>     if [[ -n $ZSH_VERSION ]]; then
>         local file=${funcfiletrace[1]%:*}
>         local line=${funcfiletrace[1]#*:}
>     elif [[ -n $BASH_VERSION ]]; then
>         local caller=$(caller 0);
>         local file=${caller##* }
>         local line=${caller%% *}
>     fi
>     echo "Caught error $error at $file:$line: $(cat $file | head -$line |
> tail -1)" >&2
>     return $error;
> }


> trap err-exit ERR
> if [[ -n $ZSH_VERSION ]]; then
>     alias init=''
> elif [[ -n $BASH_VERSION ]]; then
>     # It looks like in Bash the ERR trap must be set in every function
>     shopt -s expand_aliases
>     alias init='trap err-exit ERR'
> fi


> function fooA1() { init;               false        ;
>           }
> function fooA2() { init; if true; then false        ; fi
>          }
> function fooA3() { init;             { false        ; } always { true; }
>          }
> function fooA4() { init;             { false        ; }
>           }


> function fooB1() { init;               false && true;
>           }
> function fooB2() { init; if true; then false && true; fi
>          }
> function fooB3() { init;             { false && true; } always { true; }
>          }
> function fooB4() { init;             { false && true; }
>           }


> function fooC1() { init;               false && true                    ;
> echo foo; }
> function fooC2() { init; if true; then false && true; fi                ;
> echo foo; }
> function fooC3() { init;             { false && true; } always { true; };
> echo foo; }
> function fooC4() { init;             { false && true; }                 ;
> echo foo; }


> function bar() {
>     init
>     echo Start
>     foo$1
>     echo End
> }


> bar "$@"


I included the "foo?3" tests because all the compound commands in loop.c
seem to behave the same except for "exectry", which lacks the following
line:

  this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END);


 I included the "foo?4" tests because sequences are not handled by one of
the functions in loop.c but by some function in exec.c. However, all
"foo?3" and "foo?4" tests nevertheless behave the same as the matching
"foo?2" tests.

Here are the results:

        Zsh 5.8.1      Zsh 5.9.*      Bash 5.1.16



fooA1   Exit in foo*   Exit in foo*   Exit in foo*
> fooA2   Exit in foo*   Exit in foo*   Exit in foo*



fooB1   Exit in bar    Exit in bar    Exit in bar
> fooB2   No exit        Exit in foo*   Exit in bar



fooC1   No exit        No exit        No exit
> fooC2   No exit        Exit in foo*   No exit


My understanding is that Bash's behavior is the correct one.

Philippe

[-- Attachment #2: Type: text/html, Size: 12162 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread
* Tests RE behavior of ERR_EXIT
@ 2022-11-09  5:29 Bart Schaefer
  2022-11-10  5:22 ` [PATCH] More ERR_EXIT (was Re: Tests RE behavior of ERR_EXIT) Bart Schaefer
  0 siblings, 1 reply; 28+ messages in thread
From: Bart Schaefer @ 2022-11-09  5:29 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 318 bytes --]

Changed a set of tests from success to xfail.  Anyone have ideas of
why these aren't working?

If I change the ( subshell ) constructs to use
$ZTST_testdir/../Src/zsh -fc then they all correctly exit on nonzero
status as expected.

Aside, should 'setopt err_return' in the nested function test be using
localoptions ?

[-- Attachment #2: errexit_xfail.txt --]
[-- Type: text/plain, Size: 1901 bytes --]

diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst
index f120809a7..e3d9ea871 100644
--- a/Test/C03traps.ztst
+++ b/Test/C03traps.ztst
@@ -720,14 +720,15 @@ F:Must be tested with a top-level script rather than source or function
 0:ERR_RETURN in "else" branch in nested function
 >Good
 
+  unsetopt err_return	# "leaked" from previous test
   (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
+1f:ERR_EXIT triggered by status 1 at end of for
+F:This fails to exit for unknown reasons and prints OK
 
   (setopt err_exit
   integer x=0
@@ -736,8 +737,8 @@ F:Must be tested with a top-level script rather than source or function
   done
   print OK
   )
-0:ERR_EXIT not triggered by status 1 at end of while
->OK
+1f:ERR_EXIT triggered by status 1 at end of while
+F:This fails to exit for unknown reasons and prints OK
 
   (setopt err_exit
   repeat 1; do
@@ -745,8 +746,8 @@ F:Must be tested with a top-level script rather than source or function
   done
   print OK
   )
-0:ERR_EXIT not triggered by status 1 at end of repeat
->OK
+1f:ERR_EXIT triggered by status 1 at end of repeat
+F:This fails to exit for unknown reasons and prints OK
 
   (setopt err_exit
   if true; then
@@ -754,8 +755,8 @@ F:Must be tested with a top-level script rather than source or function
   fi
   print OK
   )
-0:ERR_EXIT not triggered by status 1 at end of if
->OK
+1f:ERR_EXIT triggered by status 1 at end of if
+F:This fails to exit for unknown reasons and prints OK
 
   (setopt err_exit
   {
@@ -763,8 +764,8 @@ F:Must be tested with a top-level script rather than source or function
   }
   print OK
   )
-0:ERR_EXIT not triggered by status 1 at end of { }
->OK
+1f:ERR_EXIT triggered by status 1 at end of { }
+F:This fails to exit for unknown reasons and prints OK
 
   unsetopt err_exit err_return
   (setopt err_exit

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2022-11-16 14:22 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-12 22:16 [PATCH] More ERR_EXIT (was Re: Tests RE behavior of ERR_EXIT) Philippe Altherr
2022-11-13  3:59 ` Philippe Altherr
2022-11-13  4:11   ` Bart Schaefer
2022-11-13 13:55     ` Philippe Altherr
2022-11-13 14:24       ` Philippe Altherr
2022-11-13 15:45         ` Philippe Altherr
2022-11-13 16:52           ` Bart Schaefer
2022-11-13 16:45       ` Bart Schaefer
2022-11-13 16:53         ` Bart Schaefer
2022-11-13 18:37           ` Philippe Altherr
2022-11-13 20:55             ` Philippe Altherr
2022-11-13 22:27               ` Bart Schaefer
2022-11-13 23:10               ` Lawrence Velázquez
2022-11-13 22:12             ` Bart Schaefer
2022-11-15  1:11         ` Bart Schaefer
2022-11-15  7:01           ` [PATCH] Even more ERR_EXIT (was Re: More ERR_EXIT " Bart Schaefer
2022-11-15  7:30             ` Philippe Altherr
2022-11-15 19:50               ` Philippe Altherr
2022-11-15  7:26           ` [PATCH] More ERR_EXIT (was " Philippe Altherr
2022-11-15 19:18             ` Philippe Altherr
2022-11-15 21:08               ` Bart Schaefer
2022-11-16  2:41               ` Lawrence Velázquez
2022-11-16  6:31                 ` Philippe Altherr
2022-11-16  5:51               ` Bart Schaefer
2022-11-16  7:56                 ` Philippe Altherr
2022-11-16 14:21                   ` Philippe Altherr
  -- strict thread matches above, loose matches on Subject: below --
2022-11-09  5:29 Tests RE behavior of ERR_EXIT Bart Schaefer
2022-11-10  5:22 ` [PATCH] More ERR_EXIT (was Re: Tests RE behavior of ERR_EXIT) Bart Schaefer
2022-11-10  5:47   ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).