On Wed, Aug 6, 2008 at 7:13 AM, Christian Jaeger <[EMAIL PROTECTED]> wrote: > $ bash -c '( set -e ; false; echo "hu?" ) || echo "false"' > hu? > # expecting "false" > > $ bash -c '( set -e ; false; echo "hu?" ); if [ $? -ne 0 ]; then echo > "false"; fi' > false > > # Also: > $ bash -c '( set -e ; false; echo "hu?" ) && echo "false"' > hu? > false > # expecting no output
On Wed, Aug 6, 2008 at 10:42 AM, Christian Jaeger <[EMAIL PROTECTED]> wrote: > http://www.opengroup.org/onlinepubs/009695399/utilities/set.html This is bad documentation and ambiguous standardization. The linked opengroup standard includes the wording > When this option is on, if a simple command [fails or exits with status >0], > and is not ... and is not ... and is not ..., then the shell shall > immediately exit. What is not specified is whether the scope of the "and is not" conditions extends outside the subshell created by a fork or not. Does the meaning of a script enclosed in parenthesis depend on what appears outside parenthesis? The behavior of bash clearly shows the answer is "yes", at least in this case. Is this documented? Thus, in the above definition for set -e, assume the simple command ("false" in the example) meets all of the "and is not" conditions" locally within the parenthesis. Then if the parenthesis enclosed fragment taken as a simple command also meets all of the "and is not" conditions, then "the shell shall immediately exit" means "the subshell shall immediately exit and the shell shall not exit". That is, the child process shall exit and the parent process shall resume execution at the close parenthesis. Thus, "exit" is taken relative to the subshell, but the conditions are taken relative to the whole script. Otherwise, "the shell shall immediately exit" actually means "the subshell shall not exit." That is, the child process, upon finding that the simple command has failed, looks in the forked memory image at the state inherited from all its ancestors and notes that one of them has registered a failure handler, and therefore decides to ignore the failure without even looking at the set -e flag. The semantics of "set -e; false; echo unreachable" depends on the state of the interpreter when the script fragment is executed, and cannot be determined without reference to inherited state. This also applies when the fragment appears within a function: the semantics varies from call to call. I think the standard needs to refer to the state of the interpreter in defining the semantics of set -e, rather than pretending that the meaning is context free.