I have a weird situation where inserting any command that succeeds in the line above makes command substitution ($(I mean this)
) not work as expected — it does not exit, even though the command fails and err_exit is set.
I keep thinking it must be something to do with subshells behaving differently from what I think they should, but I can't quite put my finger on it.
This prints “should have exited above”:
#!/usr/bin/env zsh
setopt local_options err_exit warn_create_global nounset
local x
if false; then
else
x=$(false)
echo 'should have exited above'
fi
This prints nothing:
#!/usr/bin/env zsh
setopt local_options err_exit warn_create_global nounset
local x
if false; then
else
true
x=$(false)
echo 'should have exited above'
fi
Obviously I can make my script work correctly by leaving that true
in, but it doesn't seem correct and I can't even explain it. So what is happening, and what is the recommended solution?
Best Answer
It's a bug. Here's a smaller test case.
The assignment
x=$(false)
should have the status of the last command substitution in it, which is 1. Withoutset -e
, this snippet should print1
followed by the active shell options. Withset -e
, this snippet should exit before it prints anything.Zsh 5.1.1 works correctly (exit with status 1). Dash, bash, mksh, ksh93 all have the same behavior.
Zsh checked out from Git today prints
1 569Xe
and exits with status 0. If you add a call tofalse
beforeecho
, the script exits as expected. It looks likeerrexit
has no effect onx=$(false)
even though it should.git bisect
says b581c3fece76c87ed86ae9fc704d0fcf208a79d3 is the first bad commit.It's now been reported on the zsh workers mailing list and fixed a few hours later in that commit which will be included in the next release.