tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Next steps for /bin/sh

    Date:        Sat, 27 Feb 2016 15:13:28 +0800 (PHT)
    From:        Paul Goyette <>
    Message-ID:  <>

  | On Sat, 27 Feb 2016, Robert Elz wrote:

  | > That one relates to what
  | > 	sh -c 'set -e; false && false; echo foo'
  | > should do.

  | In my opinion, having the standard finally updated is a big step in the 
  | right direction.

Yes, it is, but ...

And in a different message:

Martin Neitzel <> said:
  | I cannot test my SunOS-4 sparc at the moment, but I still actively use my
  | ultrix-4.4 DECsystem with a comparable [pre-SysV, pre-function()] sh(1):

  | It does the right thing, i.e. exit before the "echo".

  | > So, should we change it?   If so, I'll look into what code needs altering.

  | Yepp, please. 

Unfortunately, I can't, because it turns out when I looked more closely,
it isn't broken after all (or not according to the std).

The reasoning is as follows ...

When the first "false" in   false && false   is executed, its exit status
is being checked by the && operator, so -e does not apply to it.
(Everyone agrees with this.)

When the second "false" is executed ... well, that would be a major bug
in the shell if it were (and fortunately, that bug does not exist) as
the && short-circuits evaluation, once the command on the left has failed,
that's it.  So that false is never executed, so it never has an exit
status to trigger the -e shell exit.   If it were executed it would do
that (you can verify that by trying "true && false" instead of "false && 

So, all that's left is the overall result of the compound command.  That
will be 1, which could cause -e to apply.   But it doesn't - it used not
to in the standard because or wording relating to simple commands.
But that was too ambiguous, and didn't catch all the cases.  So it
has been changed now, but the effect in this case is the same.

Now, the standard says that if a non-zero result from a compound command
(other than a sub-shell, which this is not) is the result of a command
failing in a situation where the -e gets ignored, then the status of the
compound command is also ignored for -e purposes.   Here, the 1 exit code
from the && compound comes from the exit of the first false.  When that
one ran, its exit code was ignored for -e purposes, so we also ignore -e
for the compound.


So, after all, it is not a surprise that all modern shells do the same
as the NetBSD shell does, and there is nothing to fix in this area.

One item off the list.   Onto the next.


ps: just in case it is not obvious from what is above

	sh -c 'set -e; (false && false); echo foo'

does exit(1), and not echo foo.  Neither "false" causes an exit,
the && result doesn't either.   But the subshell also has an exit
status of 1, and subshells don't care why the exit status of the
commands inside was not zero (they cannot, the parent process has
no way to know what failed in the child process, just the exit
status it returned.)   So, when the subshell returns a non-zero status,
with -e set, bye bye shell.

Home | Main Index | Thread Index | Old Index