set -e behaviour. Seems bug. Not the subshell issue!

221 views
Skip to first unread message

Марк Коренберг

unread,
Sep 11, 2012, 7:51:02 AM9/11/12
to bug-...@gnu.org
Hello.

Example:
---------------------------------------
#!/bin/bash

set -e -u -E -T

fun()
{
echo 'Execute really bad command:'
/bin/false
echo 'should not print this'
return 0
}

if ! fun; then
echo 'should catch fault here'
fi

fun
---------------------------------------

"should not print this" should not be printed (as I think) in any case.
But in first case, it's printed, in second - is not.

(I have tested in bash 2.0 ... 4.2.24)

Is any way to force "set -e" to work even in such cases?

If this question asked 1000 times, why not to answer in FAQ (
http://tiswww.case.edu/php/chet/bash/FAQ)?

--
Segmentation fault

Eric Blake

unread,
Sep 11, 2012, 8:07:42 AM9/11/12
to Марк Коренберг, bug-...@gnu.org
On 09/11/2012 05:51 AM, Марк Коренберг wrote:
> fun()
> {
> echo 'Execute really bad command:'
> /bin/false
> echo 'should not print this'
> return 0
> }
>
> if ! fun; then
> echo 'should catch fault here'

Wrong. '! fun' is executed in a context in which 'set -e' is ignored,
so ALL commands with 'fun' are executed without error aborts, which mean
'should not print this' MUST be printed, and 'should catch fault here'
must NOT be printed.

This behavior conforms to POSIX.

>
> Is any way to force "set -e" to work even in such cases?

No, it is already working as specified (just not the way you want).

>
> If this question asked 1000 times, why not to answer in FAQ (
> http://tiswww.case.edu/php/chet/bash/FAQ)?

http://mywiki.wooledge.org/BashFAQ#BashFAQ.2BAC8-105.Why_doesn.27t_set_-e_.28or_set_-o_errexit.2C_or_trap_ERR.29_do_what_I_expected.3F

--
Eric Blake ebl...@redhat.com +1-919-301-3266
Libvirt virtualization library http://libvirt.org

signature.asc

Марк Коренберг

unread,
Sep 11, 2012, 11:24:39 AM9/11/12
to bug-...@gnu.org
2012/9/11 Eric Blake <ebl...@redhat.com>

> On 09/11/2012 05:51 AM, Марк Коренберг wrote:
> > fun()
> > {
> > echo 'Execute really bad command:'
> > /bin/false
> > echo 'should not print this'
> > return 0
> > }
> >
> > if ! fun; then
> > echo 'should catch fault here'
>
> Wrong. '! fun' is executed in a context in which 'set -e' is ignored,
> so ALL commands with 'fun' are executed without error aborts, which mean
> 'should not print this' MUST be printed, and 'should catch fault here'
> must NOT be printed.
>
> This behavior conforms to POSIX.
>
> >
> > Is any way to force "set -e" to work even in such cases?
>
> No, it is already working as specified (just not the way you want).
>
> >
> > If this question asked 1000 times, why not to answer in FAQ (
> > http://tiswww.case.edu/php/chet/bash/FAQ)?
>
>
> http://mywiki.wooledge.org/BashFAQ#BashFAQ.2BAC8-105.Why_doesn.27t_set_-e_.28or_set_-o_errexit.2C_or_trap_ERR.29_do_what_I_expected.3F


Huge thanks for the answer. But faq does not explain this behaviour. So,
questions:
1. Can you give me link (or name of) posix standard where I can read about
this?
2. Is there any workaround (like shopt) that will help for such case? I
have read all shopts, man bash and found nothing.

If it is the POSIX standard, this mean that I can not check return value of
custom function at all, as this implies disabling of "set -e" inside
functions bodies.

>
>
> --
> Eric Blake ebl...@redhat.com +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
>
>


--
Segmentation fault

Greg Wooledge

unread,
Sep 11, 2012, 11:36:55 AM9/11/12
to ???????? ??????????????????, bug-...@gnu.org
On Tue, Sep 11, 2012 at 09:24:39PM +0600, ???????? ?????????????????? wrote:
> 1. Can you give me link (or name of) posix standard where I can read about
> this?

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_25

"When this option is on, if a simple command fails for any of the reasons
listed in Consequences of Shell Errors or returns an exit status value >0,
and is not part of the compound list following a while, until, or if keyword,
and is not a part of an AND or OR list, and is not a pipeline preceded by the
! reserved word, then the shell shall immediately exit."

In your original example, which I believe looked something like:

if ! myfunc; then

set -e is not in effect for two reasons: the if, and the !. Either one
would be sufficient to disable it. You've got both.

> 2. Is there any workaround (like shopt) that will help for such case? I
> have read all shopts, man bash and found nothing.

The workaround is "stop trying to use set -e".

Eric Blake

unread,
Sep 11, 2012, 12:10:40 PM9/11/12
to Марк Коренберг, bug-...@gnu.org
On 09/11/2012 09:24 AM, Марк Коренберг wrote:
>> This behavior conforms to POSIX.
>>
>>>
>>> Is any way to force "set -e" to work even in such cases?
>>
>> No, it is already working as specified (just not the way you want).
>>

> 1. Can you give me link (or name of) posix standard where I can read about
> this?

POSIX 2008 Technical Corrigendum 1 is not quite out yet (still in
balloting, but will be finalized later this year), but it will include
this wording:

http://www.austingroupbugs.net/view.php?id=52

> 2. Is there any workaround (like shopt) that will help for such case? I
> have read all shopts, man bash and found nothing.

There's nothing to work around. 'set -e' is behaving as required by
POSIX, which just happens to be a different behavior than what you want.
There is no option in bash to get the behavior you want, unfortunately.

>
> If it is the POSIX standard, this mean that I can not check return value of
> custom function at all, as this implies disabling of "set -e" inside
> functions bodies.

It doesn't disable 'set -e' inside ALL function bodies, but only inside
function bodies where the function call appears inside a context where
'set -e' is ignored (such as in the condition of 'if'). It's
non-intuitive, and therefore my advice is to never rely on 'set -e'.
signature.asc
Reply all
Reply to author
Forward
0 new messages