[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: set -e in (subshells) does not work independently of outer context
From: |
Eric Blake |
Subject: |
Re: set -e in (subshells) does not work independently of outer context |
Date: |
Wed, 25 Jan 2012 09:15:29 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:9.0) Gecko/20111222 Thunderbird/9.0 |
[re-adding the list - also, please don't top-post on technical lists]
On 01/24/2012 06:53 PM, Jim Avera wrote:
> Thanks for the quick reply. I read the referenced article and don't
> think it says that at all.
> (http://austingroupbugs.net/view.php?id=52). In fact it seems to imply
> that -e *should* work inside subshell commands even if -e is otherwise
> being ignored (presumably because it is in a conditional context, etc.):
>
> <quote>
> 3) If the exit status of a compound command **other than a subshell**
> command was the result of a failure while -e was being ignored, then -e
> shall not apply to this command. </quote> [emphasis added]
>
> So what is the implication of this statement if the compound -is- a
> subshell command? Why was the exception "other than a subshell command"
> specified?
> Presumably -e should apply regardless of whether it was being ignored
> outside in such cases.
>
> I checked, and bash's current behavior matches ksh. So it is compatible.
>
> But as I read the specification, bash (and ksh) do something different.
Consider:
$ ksh -c 'set -e; { false && :; }; echo $?'
1
$ bash -c 'set -e; { false && :; }; echo $?'
1
This echoes 1. Why? Inside the compound command, we have an AND-OR
list; which means that the left half of the list is in a context where
-e is ignored (the 'false'); but based on the semantics of &&, the right
half is not executed. That means the overall compound command (the '{
false && :; }') executed with a failure - but the _reason_ it failed was
due to a failure of the AND-OR command, which was in turn due to the
failure of the simple command 'false' in a context where -e is ignored.
Therefore, the compound command has a non-zero status, but does not
trigger an exit for -e, even though -e is in effect for the overall
compound command.
Now, repeat the test with a subshell:
$ ksh -c 'set -e; ( false && : ); echo $?'
$ bash -c 'set -e; ( false && : ); echo $?'
Notice - no exit status. Why? Because sub-shells are the only compound
command where a non-zero status, caused for any reason (including
reasons where set -e was ignored), is fatal to the parent script.
That's what point 3 is trying to tell you.
Point 3 is _not_ requiring subshells to override the contexts where set
-e is ignored. That is, once you are in a context where -e is ignored,
there is NOTHING you can do to get -e obeyed again, not even a subshell.
$ bash -c 'set -e; if (set -e; false; echo hi); then :; fi; echo $?'
hi
0
Even though we called set -e twice (both in the parent and in the
subshell), the fact that the subshell exists in a context where -e is
ignored (the condition of an if statement), there is nothing we can do
in the subshell to re-enable -e.
--
Eric Blake eblake@redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature