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

Re: Inconsistent behavior of ERR_EXIT with conditionals



On Tue, Nov 8, 2022 at 10:51 AM Philippe Altherr
<philippe.altherr@xxxxxxxxx> wrote:
>
> Let me try to illustrate with a more concrete example why I think Zsh's behavior could/should be improved. Consider that a first developer wrote the following code:
>
>> #!/bin/zsh -e

The first developer is wrong.  That's not what -e is for.  A script
should be correct WITHOUT the use of -e ... the purpose of -e is to
uncover cases where the developer made a mistake, not to be an
integral part of the script function.

> On Tue, Nov 8, 2022, at 12:36 AM, Bart Schaefer wrote:
>>
>> ERR_EXIT kicks in only when the result is not otherwise checked.
>
> Unfortunately there are several cases where Zsh doesn't behave like that. For example, consider the following commands:
>
>> { false; true } || true; echo $?
>> if false; true; then echo 0; else echo 1; fi

Again, wrong.  "{ false; true }" is a single statement because of the
braces.  When that statement is followed by || the result of the
ENTIRE statement is considered to have been "checked".
Similarly, in "if false; true; then" the conditional part is
considered as a single statement whose result is "checked".

As Lawrence has said, you're discarding the POSIX definition of how
"set -e" is intended to work.

> There are other cases where ERR_EXIT is triggered but fails to propagate. A major offender in that regard is the following code:
>
>> local var=$(false); echo $?
>
> In this case "false" triggers an ERR_EXIT but it only exits the sub-shell of the command substitution.

This is explicitly called out in the documentation:

     Unlike parameter assignment statements, typeset's exit status on an
     assignment that involves a command substitution does not reflect
     the exit status of the command substitution.  Therefore, to test
     for an error in a command substitution, separate the declaration of
     the parameter from its initialization:

          # WRONG
          typeset var1=$(exit 1) || echo "Trouble with var1"

          # RIGHT
          typeset var1 && var1=$(exit 1) || echo "Trouble with var1"

> However, having to systematically use this style is rather cumbersome. Furthermore it's not even foolproof. Indeed, if there are multiple command substitutions, the assignment returns the exit status of the last one. Thus, the following command does NOT exit and prints "0":
>
>> local var; var=$(false)$(true); echo $?

This also follows bash and presumably POSIX behavior.

> Is there any chance that Zsh could be changed to more closely follow the specification above?

No.




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