ATTENTION: This patch depends on the following patches described
here:
- patch-01-revert-mistaken-errexit-patches.txt
- patch-03-fix-negation-statement.txt
I have found another issue in execlist, which affects the behavior of ERR_RETURN in convoluted cases that involve at least two &&/|| commands and a function call. The following example exhibits the issue.
set -o err_return
fn() { { false; echo fn1 } && echo fn2 }
fn; echo done
fn && echo done
The execution of "fn; echo done" prints "fn1", "fn2", and "done". The execution of "fn && echo done" should print the same but currently prints nothing.
The problem is that
this test in "execlist" is too conservative. Inside "fn", "oldnoerrexit" is equal to "NOERREXIT_EXIT". Indeed the "&&" in "fn && echo done" first sets "noerrexit" to "NOERREXIT_EXIT | NOERREXIT_RETURN". The call to "fn" then removes "NOERREXIT_RETURN". Thus, at the beginning of "execlist" in the call to "fn", "noerrexit" is equal to "NOERREXIT_EXIT" and "oldnoerrexit" is initialized to the same value. Since "oldnoerrexit" is non-zero,
the test fails to readd "NOERREXIT_RETURN" for the evaluation of "{ false; echo fn1 }". Therefore the evaluation of "false" triggers an early return of "fn" wîth exit status 1, which in turn triggers an early return of the toplevel and thus nothing is printed.
The solution is to unconditionally set "noerrexit" to "NOERREXIT_EXIT | NOERREXIT_RETURN" for any command on the left of "&&" and "||" (and for any command on the right of "!"). The patch does exactly that (and adds a regression test).
Philippe