set -e is not clearly documented

2013-10-07 Thread Bartłomiej Palmowski
Hi,

lets consider the following:

$ echo $BASH_VERSION
4.1.2(1)-release
$ cat /etc/system-release
Red Hat Enterprise Linux Server release 6.3 (Santiago)
$ ( set -e; echo foo; false; echo bar; ) # this one is expected
foo
$ ( set -e; echo foo; false; echo bar; ) || true # this one is not expected
foo
bar

documentation (http://www.gnu.org/software/bash/manual/bash.html) states
that:

[...] The shell does not exit if the command that fails is part of the
command list immediately following a while or until keyword, part of the
test in an if statement, part of any command executed in a && or || [...]

In this case it is not clear since set -e is invoked inside subshell and ||
is outside this subshell.

What I would expect to happen is ( set -e; echo foo; false; echo bar; ) ||
exit $? to exit with exit code of a last failed command in a subshell.


Re: Command substitution and exiting from deeply nested subshells

2013-10-07 Thread Greg Wooledge
On Sun, Oct 06, 2013 at 09:37:00PM -0300, Carlos Pita wrote:
>   I'm not completely sure whether this is a bug or not but it seems
> not possible to immediately exit a shell when an error happens at 2+
> levels of subshell nesting.

Exiting in a subshell will never cause the parent shell to exit,
regardless of depth.

imadev:~$ (exit 1); echo I did not exit
I did not exit

If you want a child process (which includes subshells) to be able to
tell the parent process to terminate, then you must arrange some
interprocess communication channel to send that information.  This
could be as simple as "if I return -1, you should exit", or it could
be something more complicated involving signals, or a file, or a named
pipe.

> I've tested this with set -e, set -E, an ERR trap,

All of those are useless and should be avoided.  If handling errors
is important to you, then you should handle them.  Yourself.
See http://mywiki.wooledge.org/BashFAQ/105 for details.

Bash is required to IMPLEMENT set -e because it's in the POSIX
specification.  You are not required to USE it.



Re: set -e is not clearly documented

2013-10-07 Thread Greg Wooledge
On Mon, Oct 07, 2013 at 11:01:11AM +0200, Bart?omiej Palmowski wrote:
> $ ( set -e; echo foo; false; echo bar; ) # this one is expected
> foo
> $ ( set -e; echo foo; false; echo bar; ) || true # this one is not expected
> foo
> bar

set -e is useless rubbish that should be avoided.
See http://mywiki.wooledge.org/BashFAQ/105 for details.

Bash is required to IMPLEMENT set -e because it's part of the POSIX
specification.  You are not required to USE it.



Re: Command substitution and exiting from deeply nested subshells

2013-10-07 Thread Chet Ramey
On 10/6/13 8:37 PM, Carlos Pita wrote:

>   I'm not completely sure whether this is a bug or not but it seems
> not possible to immediately exit a shell when an error happens at 2+
> levels of subshell nesting.  Specifically, there is a command at the
> top-level shell waiting for the results of a command substitution.
> This second command in the first subshell is in turn waiting for the
> results of another command substitution. This innermost command fails
> but the awaiting commands still finish their execution as if the error
> never happened. I've tested this with set -e, set -E, an ERR trap,
> explicit exits at each subshell, but to no avail. Below is an example
> to reproduce it.
> 
> Repeat-By:
> 
> trap 'exit 1' ERR
> 
> set -e -E
> 
> function xxx {
>   echo xxx1
>   exit 1
>   echo xxx2
> }
> 
> function yyy {
>   echo $(xxx) yyy
> }
> 
> yyy
> 
> # => xxx1 yyy
> # I wouldn't expect the echo to print any output or execute at all.

$(xxx) is a word expansion, not a command.  Bash will only pay attention to
the exit status of command substitution in one case (x=$(foo)).  This
command substitution doesn't contribute to any other command's exit status,
especially `echo', and `set -e' doesn't cause the shell to pay attention
to it.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: set -e is not clearly documented

2013-10-07 Thread Chet Ramey
On 10/7/13 5:01 AM, Bartłomiej Palmowski wrote:
> Hi,
> 
> lets consider the following:
> 
> $ echo $BASH_VERSION
> 4.1.2(1)-release
> $ cat /etc/system-release
> Red Hat Enterprise Linux Server release 6.3 (Santiago)
> $ ( set -e; echo foo; false; echo bar; ) # this one is expected
> foo
> $ ( set -e; echo foo; false; echo bar; ) || true # this one is not expected
> foo
> bar
> 
> documentation (http://www.gnu.org/software/bash/manual/bash.html) states
> that:
> 
> [...] The shell does not exit if the command that fails is part of the
> command list immediately following a while or until keyword, part of the
> test in an if statement, part of any command executed in a && or || [...]
> 
> In this case it is not clear since set -e is invoked inside subshell and ||
> is outside this subshell.

The subshell command is clearly part of the || compound command.  The
subshell `knows' that it is part of || and set -e has no effect.  This
example has been discussed before, on this list and the austin-group
Posix list, and the bash behavior is correct.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Command substitution and exiting from deeply nested subshells

2013-10-07 Thread Carlos Pita
> $(xxx) is a word expansion, not a command.  Bash will only pay attention to
> the exit status of command substitution in one case (x=$(foo)).  This
> command substitution doesn't contribute to any other command's exit status,
> especially `echo', and `set -e' doesn't cause the shell to pay attention
> to it.

Thanks Chet, it's clear now.

> Exiting in a subshell will never cause the parent shell to exit,
> regardless of depth.

This is not true in general.
set -e; (exit 1); echo "I don't exist"

>> I've tested this with set -e, set -E, an ERR trap,
> All of those are useless and should be avoided.

Ok, I'm not particularly interested in using them, I was just
reinforcing my point.

Best regards
--
Carlos



Re: Command substitution and exiting from deeply nested subshells

2013-10-07 Thread Greg Wooledge
On Mon, Oct 07, 2013 at 11:58:48AM -0300, Carlos Pita wrote:
> > Exiting in a subshell will never cause the parent shell to exit,
> > regardless of depth.
> 
> This is not true in general.
> set -e; (exit 1); echo "I don't exist"

In this case, it is the "set -e" which may or may not cause the parent
shell to terminate, depending on which shell you're doing this in.

imadev:~$ bash-4.3 -c 'set -e; (exit 1); echo "I do not exist"'
imadev:~$ bash-4.2 -c 'set -e; (exit 1); echo "I do not exist"'
imadev:~$ bash-4.1 -c 'set -e; (exit 1); echo "I do not exist"'
imadev:~$ bash-4.0 -c 'set -e; (exit 1); echo "I do not exist"'
imadev:~$ bash-3.2 -c 'set -e; (exit 1); echo "I do not exist"'
I do not exist

The exit itself is *not* propagated upward, and please see my previous
comments about the reliability and usefulness of set -e (i.e. none).