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:

NetBSD Home
NetBSD PR Database Search

(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.