bug-bash
[Top][All Lists]
Advanced

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

Re: command substitution is stripping set -e from options


From: Linda Walsh
Subject: Re: command substitution is stripping set -e from options
Date: Mon, 12 Oct 2015 09:10:33 -0700
User-agent: Thunderbird



Chet Ramey wrote:
On 10/2/15 9:22 AM, Greg Wooledge wrote:
On Fri, Oct 02, 2015 at 03:53:42PM +0300, Christoph Gysin wrote:
I'm still curious as to why set -e is stripped in the first place?
Chet can give the definitive answer, but my take is that it's a huge
surprise to someone writing a function independent of the script, or
using a function that was written independently of the script.
---
        It used to not be so surprising before the action of set -e was
changed to signal fail on non-simple commands returning non-zero return
codes. Set -e used to be useful -- mostly during devel, but even in some "working" software to catch errors where the developer wasn't expecting
a fail from some command.

Having to write failure code for everything made set-e useless.
A self-fulfilling truth, at the time, for those who argued that set-e
was useless the way it previously functioned, so anything that changes
its behavior should be considered a 'no-op', because it was already
broken (for them).  No one seemed to get the circular reasoning
in use there.

Before, auto-err-exit only happened on on **simple** (external) commands, but now builtins, like ((a=0));echo $? will trigger a exception with the ((a=0)) (because in calculations, a value of 0 is the only 'true' value. That was probably one of the more stupid effects of the
new set-e changes -- that bash in non-posix mode should emulate
the posix behavior and throw a errexit if a lone calculation yields 0, and
made bash up to 22x slower on some numeric calcs

0) null case (no calculation)
time (i=1000000 && while((--i));do : ; done)
3.84sec 3.84usr 0.00sys (100.03% cpu)

1) simple calc, pre set-e change:
time (i=1000000 && while((--i));do ((a=0)); done)
3.92sec 3.91usr 0.00sys (100.01% cpu)

simple calc - null case (removing loop costs) = .08s/1M-loops
2) using post set-o posix approved syntax:

time (i=1000000 && while((--i));do let a=0 ; done)
5.72sec 5.72usr 0.00sys (100.01% cpu)

Posix pushed change in set-e case (minus null loop) = 1.88s/1M-loop
or 22.5X the simple case.



It's been over 20 years, and we weren't as detailed with our change logs
back then, but I imagine the rationale was similar to the above with the
addition of something like the following:

The parent shell (the one that enabled -e) should be the one to make the
decision about whether or not the shell exits.  The exit status of the
command substitution doesn't make a difference except in one special case,
so inheriting errexit and exiting (possibly prematurely) doesn't really
help the parent decide whether or not to exit.
---
        Wasn't it still the case that an error in the function:
could be caught in the parent by something like:

funcall || { stat=$?; possible_altfunc or die $stat "msg" ;} ---


Now, of course, it's been more than 20 years, and backwards compatiblity
is a concern.
---
        It wasn't so much, when set-e was changed only a few years ago. ;-/

Besides, what would be wrong with a env BASH_SETFLAG_MASK that could mask out set values that would auto-change in a function (or some similar mechanism). I had to write some workaround code to support '-x' staying on in functions, as well as having the effect of localizing any '-x' change to the function.
(i.e. at beginning of function, restore global value of -x, at end of function
restore previous global value again)

Usually -- if I was tracing, I wanted to step into most functions, but
I didn't want a function turning on tracing being propagated to the rest
of the prog.

-l



reply via email to

[Prev in Thread] Current Thread [Next in Thread]