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

Re: Inconsistent behavior of ERR_EXIT with conditionals



Hi Bart,

Thanks for your replies. Great to see that this may get fixed. I feared that it could be a case where it's too risky to change the existing behavior, even if it's incorrect. However, before fixing anything, I think that we should get a clear understanding of what is the expected behavior of ERR_EXIT. Indeed, there are more cases where I think that Zsh fails to do the right thing.

My understanding of ERR_EXIT is that it should trigger an exit of the shell immediately after any command returns with a non-zero exit status, with the exception of commands whose exit status stands for a condition (for example in the condition of an if statement or on the left of an || operator). In other words, when ERR_EXIT is enabled, any command that unexpectedly fails should trigger an immediate exit of the shell.

Below is a short script that exhibits most of the cases that I know where Zsh fails to behave as described above. The function EXIT is used everywhere where I expect Zsh to trigger an exit (sometimes from a sub-shell). In other words, none of the EXIT function calls should be executed. Unfortunately, all the calls with an argument "Failure-?" are executed.

#!/bin/zsh -e

function EXIT() { echo $1 1>&2 }

: $(false; EXIT Success-A); EXIT Failure-a
local v=$(false; EXIT Success-B); EXIT Failure-b
if false; EXIT Failure-c; true; then true; fi
{ false; EXIT Failure-d; true } && true
false && true; EXIT Failure-e
! true; EXIT Failure-f

The output is the following:

Failure-a
Failure-b
Failure-c
Failure-d
Failure-e
Failure-f
 
Regarding your proposed fix, I'll have to take a closer look. A few days ago, I looked at exec.c, noticed the noerrexit variables, and figured that was probably the key to some of the bugs but I would need much more time to understand what exactly is going on. I'll at least try to build Zsh on my machine so that I can try your fix.

Philippe


On Mon, Nov 7, 2022 at 4:50 AM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
On Sun, Nov 6, 2022 at 12:45 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> [...] I suspect this fix may be needed elsewhere ... there are a
> bunch of similar cases for multi-line shell constructs in Src/loop.c

Those are:
  for
  select
  while
  repeat
  if
  case

Does anyone disagree that Philippe's examples demonstrate that "if"
and "case" should get this treatment?

More questionable are the looping constructs.  I can't come up with a
way to have the loop end in an error state without the whole shell
ERREXITing before reaching the end of the loop body.  The value of
this_noerrexit matters at all, as far as I can tell, only to suppress
the false-condition that ends a "while" loop, and is meaningless in
for/select/repeat?


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