NetBSD Problem Report #32282
From www@netbsd.org Mon Dec 12 03:01:25 2005
Return-Path: <www@netbsd.org>
Received: by narn.netbsd.org (Postfix, from userid 31301)
id C048163B8CD; Mon, 12 Dec 2005 03:01:25 +0000 (UTC)
Message-Id: <20051212030125.C048163B8CD@narn.netbsd.org>
Date: Mon, 12 Dec 2005 03:01:25 +0000 (UTC)
From: pstoeber@uni-potsdam.de
Reply-To: pstoeber@uni-potsdam.de
To: gnats-bugs@netbsd.org
Subject: set -e - difference between /bin/sh and /bin/ksh
X-Send-Pr-Version: www-1.0
>Number: 32282
>Category: bin
>Synopsis: set -e - difference between /bin/sh and /bin/ksh
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Dec 12 03:05:00 +0000 2005
>Closed-Date: Sun Feb 21 17:01:51 +0000 2016
>Last-Modified: Sun Feb 21 17:01:51 +0000 2016
>Originator: Paul Stoeber
>Release: 3.0 RC5
>Organization:
>Environment:
NetBSD 3.0_RC5 NetBSD 3.0_RC5 (GENERIC_LAPTOP) #0: Thu Dec 1 01:51:05 UTC 2005 builds@b4.netbsd.org:/home/builds/ab/netbsd-3-0-RC5/i386/200511302123Z-obj/home/builds/ab/netbsd-3-0-RC5/src/sys/arch/i386/compile/GENERIC_LAPTOP i386
>Description:
$ /bin/sh -c 'set -e; true | false; echo $?'
1
$ /bin/sh -c 'set -e; (false); echo $?'
1
$ /bin/ksh -c 'set -e; true | false; echo $?'
$ /bin/ksh -c 'set -e; (false); echo $?'
$
I don't know if uniformity is desired here.
I find ksh's behavior less surprising, because it's closer to the "if something goes wrong, stop" meaning of set -e.
>How-To-Repeat:
>Fix:
modify src/bin/sh/eval.c ?
>Release-Note:
>Audit-Trail:
From: David Laight <david@l8s.co.uk>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/32282: set -e - difference between /bin/sh and /bin/ksh
Date: Mon, 12 Dec 2005 15:28:04 +0000
On Mon, Dec 12, 2005 at 03:05:01AM +0000, pstoeber@uni-potsdam.de wrote:
> >Number: 32282
> >Synopsis: set -e - difference between /bin/sh and /bin/ksh
> $ /bin/sh -c 'set -e; (false); echo $?'
> 1
> $ /bin/ksh -c 'set -e; (false); echo $?'
> $
I suspect the posix behaviour is that the shell should exit.
Since (...) is defined as a method of grouping commands, not as an
equivalent of sh -c '...', so when it says 'the shell should exit'
there is only one shell.
However the very similar:
sh -c 'set -e; (false && true); echo $?'
should definitely echo 1, since the 'false' doesn't cause the shell
to exit and () isn't a simple command. ksh gets this one wrong.
Unfortunately, differenciating between the two cases requires an
additional bit of information - which cannot easily be passed from
the child to parent when () is implemented using fork().
David
--
David Laight: david@l8s.co.uk
From: Robert Elz <kre@munnari.OZ.AU>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/32282
Date: Sun, 21 Feb 2016 23:54:12 +0700
This PR should be closed, the sh bug described has long been fixed.
But while I am here, text that was appended to this PR has been
quoted (in the atf sh tests) to justify some bizarre comments
(at least), and that is all nonsense - the atf tests include commented
out tests (tests that aren't run) which claim to be testing what
posix requires, and other tests (that are run) that - the atf test
comments claim - test the incorrect NetBSD way.
But in (I think all) of those the quoted posix way is nothing of the
kind, it is utter nonsense, and the "NetBSD way" (which is tested)
is also the POSIX way. (That isn't to say that NetBSD sh and the std
never diverge - they do sometimes, mostly for good reason, but none
of those are (currently) being tested, or not that I have seen so far.)
I know this PR, and its added comments, are > 10 years old now, and
the posix standard has been amended (several times I think) in that
period, clarifying stuff that was less than obvious before.
But this comment in the PR ...
I suspect the posix behaviour is that the shell should exit.
is agreeing that the reported behaviour was a bug, which it was,
which is why it got fixed. But ...
Since (...) is defined as a method of grouping commands, not as an
equivalent of sh -c '...',
That's both wrong and right - () is not just "a method of grouping
commands" (that would be { }) it runs commands in a sub-shell, at
least notionally (and in all shells I know of, I think, in almost all
cases - certainly the ones in issue here - actually implemented that way.)
That is, the shell forks, and the child runs the sub-shell commands.
Even if not implemented that way, it must act as if it were (so nothing
in the sub-shell can affect the parent shell in any way other than passing
back an exit status, or wacky things like sending signals.)
It is also correct, it is not the equivalent of sh -c '...', that is
running a whole new shell, not just a sub-shell. The difference is
largely in the environment in which they start, sub-shells inherit
variable values (even non-exported ones), including $$ (it is the process
id of the parent shell, even in the sub-shell) opened file descriptors,
and more. New processes start fresh, including reading $ENV if defined,
and with their own $$ setting.
so when it says 'the shell should exit' there is only one shell.
so, there isn't (at least notionally) and the shell that should exit
is the sub-shell. Even if not implemented by forking, the sub-shell
must stop executing, and return its exit status to the parent.
However, if -e is set in the parent shell (which will be inherited
by the sub-shell, but wouldn't be by a sh -c invocation, unless that
was changed to sh -ec) the sub-shell will exit when a child fails
(including exiting with non-zero status, like "false" does), and that
failure of the sub-shell will then cause the parent shell to exit (unless
one of the conditions which prevents -e applying is present.)
However the very similar:
sh -c 'set -e; (false && true); echo $?'
should definitely echo 1,
No it shouldn't, and NetBSD's current /bin/sh doesn't either.
since the 'false' doesn't cause the shell to exit
That's correct, the sub-shell completes normally, commands whose
exit status is tested in command line (like that one, before the && op)
are one of the exceptions to -e processing (commands that are in a
pipeline, and are not the final command are another).
and () isn't a simple command.
That's irrelevant. Perhaps the standard once talked about simple commands,
but if so, that was always wrong - failure of a sub-shell has always caused
the parent shell to exit if -e is in effect (in the parent) (perhaps
because of the implementation issues mentioned in the following paragraph
that I am not quoting... but for whatever reason, that is how it has
always been, and that's what the standard is supposed to document.
So
ksh gets this one wrong.
No, it doesn't. Nor does NetBSD's sh, any more.
So, someone please close this ancient PR, the bug is fixed - this message
is really just to be added to the database should anyone look at the PR
sometime in the future.
kre
State-Changed-From-To: open->closed
State-Changed-By: christos@NetBSD.org
State-Changed-When: Sun, 21 Feb 2016 12:01:51 -0500
State-Changed-Why:
fixed a long time ago; explanation added
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.