On Tue, Aug 8, 2023, at 12:04 PM, cirrus.mazurka-0t--- via Bug reports for the GNU Bourne Again SHell wrote: > The following code: > > ``` bash > #!/usr/bin/env bash > > set -Eeuo pipefail > shopt -s huponexit > shopt -s inherit_errexit > > function child_function { > return 1 > } > function parent_function { > child_function > echo "parent noticed child exit code as $?" > } > function grandparent_function { > local ec > ec=0 && parent_function || ec="$?"
Commands in AND-OR lists are not subject to set -e, with the exception of the final command. So within this particular parent_function call the failing child_function command does not cause an early exit. Instead, echo is run, and its exit status (0) becomes that of parent_function. > echo "grandparent noticed parent exit code as $ec" > } > > grandparent_function > ``` > > Will surprisingly output: > > ``` > parent noticed child exit code as 1 > grandparent noticed parent exit code as 0 This behavior may surprise you, but it is documented [1]. It also conforms to POSIX [2] and is quite common: [1]: https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html [2]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set % cat foo.sh set -e child_function() { return 1 } parent_function() { child_function echo "parent noticed child exit code as $?" } grandparent_function() { ec=0 && parent_function || ec="$?" echo "grandparent noticed parent exit code as $ec" } grandparent_function % bash foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 % ksh foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 % mksh foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 % zsh foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 % dash foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 % yash foo.sh parent noticed child exit code as 1 grandparent noticed parent exit code as 0 (These are bash 5.2.15, ksh93u+ 2012-08-01, mksh R59 2020/10/31, zsh 5.9, dash 0.5.11.5, and yash 2.54.) > Changing the code to: > > ``` bash > #!/usr/bin/env bash > > set -Eeuo pipefail > shopt -s huponexit > shopt -s inherit_errexit > > function child_function { > return 1 > } > function parent_function { > child_function || return "$?" > echo "parent noticed child exit code as $?" > } > function grandparent_function { > local ec > ec=0 && parent_function || ec="$?" > echo "grandparent noticed parent exit code as $ec" > } > > grandparent_function > ``` > > Returns the expected result of: > > ``` > grandparent noticed parent exit code as 1 This version of parent_function returns early, but not because of set -e. In fact, now *every* parent_function invocation exempts child_function from set -e. What exactly is the behavior you expect? > Is there an additional setting that I need to set to fix this? Or is > this a bug in bash? It is not a bug, and as far as I know there is no setting. Here is some additional reading on set -e wrinkles: https://mywiki.wooledge.org/BashFAQ/105 https://mywiki.wooledge.org/BashPitfalls#errexit -- vq