'How to have bash inherit failures from stdin subshells

Given the following contrived code:

#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s inherit_errexit

echo 'before'

mapfile -t tuples < <(exit 1)
# ^ what option do I need to enable so the error exit code from this is not ignored

echo 'after'

Which produces:

before
after

Is there a set or shopt option that can be turned on such that <(exit 1) will cause the caller to inherit the failure, and thus preventing after from being executed? Such as what inherit_errexit and pipefail do in other contexts.



Solution 1:[1]

In bash 4.4 or later, process substitutions will set $!, which means you can wait on that process to get its exit status.

#!/usr/bin/env bash
set -Eeuo pipefail
shopt -s inherit_errexit

echo 'before'

mapfile -t tuples < <(exit 1)
wait $!

echo 'after'

mapfile itself (in general) won't have a non-zero status, because it's perfectly happy read what, if anything, the process substitution produces.

Solution 2:[2]

You can assign a variable with the output of the command. The variable assignment propagates errors from the command substitution.

t=$(exit 1)
echo 'after'
mapfile -t tuples <<<"$t"

Solution 3:[3]

If you have Bash 4.2 or later, since you are already setting errexit and pipefail, you can avoid the problem by using:

...
shopt -s lastpipe
exit 1 | mapfile -t tuples

shopt -s lastpipe causes the last command in a pipeline to be run in the current shell. See how does shopt -s lastpipe affect bash script behavior?. In this case it means that a tuples value read by mapfile can be accessed later in the code.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chepner
Solution 2 Barmar
Solution 3 pjh