Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > muc.lists.netbsd.tech.userlevel > #11704 > unrolled thread
| Started by | David Holland <dholland-tech@netbsd.org> |
|---|---|
| First post | 2026-01-14 01:18 +0000 |
| Last post | 2026-01-14 21:09 +0700 |
| Articles | 9 — 6 participants |
Back to article view | Back to muc.lists.netbsd.tech.userlevel
set -e again David Holland <dholland-tech@netbsd.org> - 2026-01-14 01:18 +0000
Re: set -e again "Greg A. Woods" <woods@planix.ca> - 2026-01-13 18:14 -0800
Re: set -e again Mouse <mouse@Rodents-Montreal.ORG> - 2026-01-13 21:30 -0500
Re: set -e again Crystal Kolipe <kolipe.c@exoticsilicon.com> - 2026-01-14 10:28 +0000
Re: set -e again Mouse <mouse@Rodents-Montreal.ORG> - 2026-01-14 07:41 -0500
Re: set -e again Crystal Kolipe <kolipe.c@exoticsilicon.com> - 2026-01-14 13:46 +0000
Re: set -e again Robert Elz <kre@munnari.OZ.AU> - 2026-01-14 21:22 +0700
Re: set -e again RVP <rvp@SDF.ORG> - 2026-01-14 13:39 +0000
Re: set -e again Robert Elz <kre@munnari.OZ.AU> - 2026-01-14 21:09 +0700
| From | David Holland <dholland-tech@netbsd.org> |
|---|---|
| Date | 2026-01-14 01:18 +0000 |
| Subject | set -e again |
| Message-ID | <aWbu963HcQMeCm2M@netbsd.org> |
I discovered the following today.
This:
set -e
f() {
echo foo
false
echo bar
}
f
as one might expect, prints "foo" and exits.
However, this:
set -e
f() {
echo foo
false
echo bar
}
f || echo baz
echo buzz
prints "foo", "bar", "buzz", and continues. Furthermore, all the
shells I have in easy reach agree on it.
This seems wrong - the exit status of the f is guarded, but the false
is not. But also, the fact that everybody agrees makes me think it's
probably the agreed result of the last round of POSIX wrangling over
the -e definition some years back.
Is this intended, and is there a way to get the user's intended
behavior of exit on unchecked failure back? (E.g. is there a different
set to get functions to return on unchecked failure that might cover
this?)
--
David A. Holland
dholland@netbsd.org
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [next] | [standalone]
| From | "Greg A. Woods" <woods@planix.ca> |
|---|---|
| Date | 2026-01-13 18:14 -0800 |
| Message-ID | <m1vfqPL-00Mo5fC@more.local> |
| In reply to | #11704 |
[Multipart message — attachments visible in raw view] — view raw
At Wed, 14 Jan 2026 01:18:47 +0000, David Holland <dholland-tech@netbsd.org> wrote:
Subject: set -e again
>
> I discovered the following today.
>
> This:
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f
>
> as one might expect, prints "foo" and exits.
>
> However, this:
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f || echo baz
> echo buzz
>
> prints "foo", "bar", "buzz", and continues. Furthermore, all the
> shells I have in easy reach agree on it.
That makes perfect sense to me.
Note that if the function invocation is not "guarded" by testing its
exit status then execution is terminated after the false statement just
as one would also expect.
Shell functions are effectively macros.
Replace the invocation of f() with its "value" and it now looks like:
$ set -e
$ { echo foo; false; echo bar; } || echo baz; echo buzz
foo
bar
buzz
$ echo $?
0
Perhaps another way to think about it is that the part wrapped in
brackets is a compound command, and indeed the manual concurs.
A function definition is most simply "f() command", and of course the
"command" part can be either a simple command or a list (i.e. a form of
compound command).
So since the compound command is followed by an operator that tests its
status, the whole compound command is executed in the guarded
environment.
The manual also says: "The function completes after having executed
_command_ with [[its]] exit status set to the status returned by
_command_." though obviously that statement doesn't take into account an
un-guarded execution of a function in a shell with errexit("set -e") set.
> Is this intended, and is there a way to get the user's intended
> behavior of exit on unchecked failure back? (E.g. is there a different
> set to get functions to return on unchecked failure that might cover
> this?
I would definitely say it is/was intended.
Perhaps as an extension the shell could override the guard if a function
definition includes a call to "set -e" within it.
--
Greg A. Woods <gwoods@acm.org>
Kelowna, BC +1 250 762-7675 RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com> Avoncote Farms <woods@avoncote.ca>
[toc] | [prev] | [next] | [standalone]
| From | Mouse <mouse@Rodents-Montreal.ORG> |
|---|---|
| Date | 2026-01-13 21:30 -0500 |
| Message-ID | <202601140230.VAA26490@Stone.Rodents-Montreal.ORG> |
| In reply to | #11704 |
> I discovered the following today.
> [...sh set -e oddity...]
> Furthermore, all the shells I have in easy reach agree on it.
So do 5.2's and even 1.4T's sh.
I also tried changing
echo foo
to
echo "foo $-"
to see if perhaps -e was getting turned off inside the function.
Apparently not; I get "foo e" regardless of whether f's return is
checked or not.
Also, interestingly, adding the three lines "local -", "set +e", and
"set -e" to the beginning of f() does not change this.
> This seems wrong
I concur, especially since I too have been unable to find any way to
get the effect of set -e within f when f is the LHS of ||. { }
doesn't help. Neither does ( ). Neither does setting -e after
defining f. Neither does setting e only within f, not in the main
script (!!). (These tests done with 5.2's sh.)
> But also, the fact that everybody agrees makes me think it's probably
> the agreed result of the last round of POSIX wrangling over the -e
> definition some years back.
If so, *quite* some years back, in that 1.4T's sh agrees. Unless
Bourne's own work did this and everyone else felt it necessary to
ensure compatibility.
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | Crystal Kolipe <kolipe.c@exoticsilicon.com> |
|---|---|
| Date | 2026-01-14 10:28 +0000 |
| Message-ID | <aWdv1ZpNO4v-29BG@exoticsilicon.com> |
| In reply to | #11704 |
On Wed, Jan 14, 2026 at 01:18:47AM +0000, David Holland wrote:
> I discovered the following today.
>
> This:
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f
>
> as one might expect, prints "foo" and exits.
>
> However, this:
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f || echo baz
> echo buzz
>
> prints "foo", "bar", "buzz", and continues. Furthermore, all the
> shells I have in easy reach agree on it.
>
> This seems wrong - the exit status of the f is guarded, but the false
> is not. But also, the fact that everybody agrees makes me think it's
> probably the agreed result of the last round of POSIX wrangling over
> the -e definition some years back.
>
> Is this intended, and is there a way to get the user's intended
> behavior of exit on unchecked failure back? (E.g. is there a different
> set to get functions to return on unchecked failure that might cover
> this?)
Does this achieve what you want?
#!/bin/sh
set -e
f() {
echo foo
false
echo bar
}
f
[ $? ] || echo baz
echo buzz
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | Mouse <mouse@Rodents-Montreal.ORG> |
|---|---|
| Date | 2026-01-14 07:41 -0500 |
| Message-ID | <202601141241.HAA04556@Stone.Rodents-Montreal.ORG> |
| In reply to | #11707 |
>> [...set -e vs shell functions...]
> Does this achieve what you want?
> #!/bin/sh
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f
> [ $? ] || echo baz
> echo buzz
I'm not the original poster, but it does not achieve what I would
expect, which is
foo
baz
buzz
That is, I would expect/want -e to cause the function to return showing
failure. Instead, it either does nothing or takes down the whole
shell.
This does achieve it, not surprisingly, but it's an ugly kludge; I
would say that neither the nested sh nor the nested set -e should be
necessary:
set -e
f() {
sh -c '
set -e
echo "foo $-"
false
echo bar
'
}
f || echo baz
echo buzz
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse@rodents-montreal.org
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | Crystal Kolipe <kolipe.c@exoticsilicon.com> |
|---|---|
| Date | 2026-01-14 13:46 +0000 |
| Message-ID | <aWeeKG8ziRu40n77@exoticsilicon.com> |
| In reply to | #11708 |
On Wed, Jan 14, 2026 at 07:41:41AM -0500, Mouse wrote:
> >> [...set -e vs shell functions...]
>
> > Does this achieve what you want?
>
> > #!/bin/sh
> > set -e
> > f() {
> > echo foo
> > false
> > echo bar
> > }
> > f
> > [ $? ] || echo baz
> > echo buzz
>
> I'm not the original poster, but it does not achieve what I would
> expect, which is
>
> foo
> baz
> buzz
>
> That is, I would expect/want -e to cause the function to return showing
> failure. Instead, it either does nothing or takes down the whole
> shell.
Ah, OK, the way I understood the OP was that 'false' taking down the whole
script was the desired/expected behaviour, but that that was not happening in
the second example with the conditional testing the exit staus of f().
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | Robert Elz <kre@munnari.OZ.AU> |
|---|---|
| Date | 2026-01-14 21:22 +0700 |
| Message-ID | <5133.1768400569@jacaranda.noi.kre.to> |
| In reply to | #11707 |
Date: Wed, 14 Jan 2026 10:28:37 +0000
From: Crystal Kolipe <kolipe.c@exoticsilicon.com>
Message-ID: <aWdv1ZpNO4v-29BG@exoticsilicon.com>
| Does this achieve what you want?
|
| #!/bin/sh
| set -e
| f() {
| echo foo
| false
| echo bar
| }
| f
| [ $? ] || echo baz
| echo buzz
I doubt it.
[ $? ] is always true. $? is never '' which is the only way that
could be false. If it were [ $? -ne 0 ] it would be closer.
But worse than that, the f call is now subject to the -e setting,
which it wasn't before - if the real f() (whatever caused the test
case to be created in the first place - no-one really wants a script
which just outputs foo bar baz buzz in this way - happened to end in
a "return 1" or similar (we must assume that is intended, or the
"|| echo ..." after its call wouldn't be there) is now going to make
the script exit, as f has failed.
Using -e is just not worth the bother, it is a nuisance, always has
been. But it makes writing simple makefiles simple - it is what
causes the make script to stop as soon as one of the commands in it
fails.
kre
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | RVP <rvp@SDF.ORG> |
|---|---|
| Date | 2026-01-14 13:39 +0000 |
| Message-ID | <5fd0838f-4677-4810-6e5d-7cda0be107b0@SDF.ORG> |
| In reply to | #11704 |
On Wed, 14 Jan 2026, David Holland wrote:
> set -e
> f() {
> echo foo
> false
> echo bar
> }
> f || echo baz
> echo buzz
>
> prints "foo", "bar", "buzz", and continues. Furthermore, all the
> shells I have in easy reach agree on it.
>
> This seems wrong - the exit status of the f is guarded, but the false
> is not. But also, the fact that everybody agrees makes me think it's
> probably the agreed result of the last round of POSIX wrangling over
> the -e definition some years back.
>
> Is this intended, and is there a way to get the user's intended
> behavior of exit on unchecked failure back? (E.g. is there a different
> set to get functions to return on unchecked failure that might cover
> this?)
>
There's a way, but, it a) involves running functions in a subshell, and b)
set +e/-e fiddling before/after each function:
```
set -e # orig.
f() {
set -e # for func.
echo foo
false
echo bar
}
set +e # for every func.
(f); rc=$?
set -e
[ $rc -eq 0 ] || echo baz
echo buzz
```
-RVP
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [next] | [standalone]
| From | Robert Elz <kre@munnari.OZ.AU> |
|---|---|
| Date | 2026-01-14 21:09 +0700 |
| Message-ID | <17878.1768399781@jacaranda.noi.kre.to> |
| In reply to | #11704 |
Date: Wed, 14 Jan 2026 01:18:47 +0000
From: David Holland <dholland-tech@netbsd.org>
Message-ID: <aWbu963HcQMeCm2M@netbsd.org>
| I discovered the following today.
I would have expected you to be aware of all this already.
| This seems wrong - the exit status of the f is guarded, but the false
| is not.
Doesn't matter, it is executing in a place to the left of a || hence
the setting of -e is ignored.
| Is this intended, and is there a way to get the user's intended
| behavior of exit on unchecked failure back?
It is, and no, there isn't. Use of -e in anything other than a list of
simple commands, one after the other, almost always runs into problems.
It was originally intended for (old style) makefile use, not for lazy
script writers.
Simply explicitly test every command's status which matters, explicitly,
and everything will work as you intend. Don't use -e, almost ever.
(And -u isn't a lot better, but at least that one is more predictable).
kre
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-admin@muc.de
[toc] | [prev] | [standalone]
Back to top | Article view | muc.lists.netbsd.tech.userlevel
csiph-web