Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0000537 [1003.1(2008)/Issue 7] Shell and Utilities Editorial Clarification Requested 2012-01-19 01:15 2012-03-08 16:59
Reporter melkov View Status public  
Assigned To ajosey
Priority normal Resolution Rejected  
Status Closed  
Name Alexander Melkov
Organization Yandex
User Reference
Section 2.14 set
Page Number 2358
Line Number 74545-74548
Interp Status ---
Final Accepted Text
Summary 0000537: for set -e, compound commands and functions case should be clarified
Description URL:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_25 [^]

Although it is clear what to do in the case of a simple command, in the case of a compound command or a function behavior is unclear. This results in a weird change of execution flow when a function is called from within `if' statement and so on.
If we take this passage literally, the entire shell should exit in case of an error status of a command called within a function or compound *command* called from `if' compound *list*?

That is, here `reach' would be printed:
 set -e
 if false; then echo unreach; fi
 echo reach

That is, here `reach' would not be printed?
 set -e
 if { false; }; then echo unreach; fi
 echo reach

Fortunately currently existing shell interpreters do not exit shell here, unfortunately they do a bad job instead, they mask -e entirely within compound commands and functions. This results, in the worst case, to alteration of command flow withing a shell function depending on the place where the function was called which is against the expectations of any sane programmer who normally expects that the function must immediately exit after the first error since he is using `set -e'.

Examples:
This command
  { set -e; false; echo ok; } && echo true
and this
  ( set -e; false; echo ok; ) && echo true
and this
  f() { set -e; false; echo ok; }; f && echo true
print 'ok' and 'true' at least in bash, sh and zsh.
Note that calling f without `&& echo true' makes the shell exit without printing 'ok'.

If my proposal is accepted, the above commands would print nothing. It should not affect existing shell scripts in negative manner.
Desired Action Remove 'simple', add 'enclosing compound command, subshell, function or '

Change:
When this option is on, if a simple command fails for any of the reasons listed in Section
2.8.1 (on page 2315) or returns an exit status value >0, and is not part of the compound list
following a while, until, or if keyword, and is not a part of an AND or OR list, and is not a
pipeline preceded by the ! reserved word, then the shell shall immediately exit.

To:
When this option is on, if a command fails for any of the reasons listed in Section
2.8.1 (on page 2315) or returns an exit status value >0, and is not part of the
compound list following a while, until, or if keyword, and is not a part of an AND or
OR list, and is not a pipeline preceded by the ! reserved word, then the enclosing
compound command, subshell, function or the shell shall immediately exit.
Tags No tags attached.
Attached Files

- Relationships
related to 0000052Closedajosey description of set -e does not match existing practice 
parent of 0001168Closedajosey Issue #537 wrongly decided 

-  Notes
(0001096)
melkov (reporter)
2012-01-19 01:23

Sorry, I had "!" disappear in "by the ! reserved word" and some other typos.
(0001097)
Don Cragun (manager)
2012-01-19 02:00

I believe that I have fixed the missing "!" and other typos in the Desired Action field noted in Note: 0001096
(0001098)
geoffclare (manager)
2012-01-19 09:38

The description of set -e is being completely rewritten in TC1. Please see 0000052 for details.
(0001100)
melkov (reporter)
2012-01-20 06:38
edited on: 2012-01-20 07:32

Thank you.
I have listed arguments why 0000052 should be discarded in Note: 0001099

(0001101)
geoffclare (manager)
2012-01-20 10:04

I think making the standard match existing practice (as in 0000052) is the right thing to do for TC1. However, we could consider making a change in Issue 8 that would require shell implementors to change the way set -e affects functions.
(0001118)
eblake (manager)
2012-02-09 17:05

If anything, the way to go about this would be to keep 'set -e' unchanged in behavior by default, where there are contexts (such as functions) where reusing 'set -e' has no effect because of the calling context; and then go about getting consensus among the various shell implementers about adding a new set option (maybe named 'set -o errreset'; good luck in finding a short option name that works for all the shells) that lifts the restriction about contexts where 'set -e' is ignored. That is:

f() { set -e; false; echo hello; }; if f; then :; fi

would continue to echo hello, but:

f() { set -e; false; echo hello; }; set -o errreset; if f; then :; fi

would let the set -e inside f() take effect, and inhibit the echo. By doing this, scripts written to the behavior of 0000052 will continue to work, and new scripts can opt-in to the more intuitive semantics.
(0001122)
bkorb (reporter)
2012-02-10 17:43

Could "calling context" be dropped for a subshell at least?

> $ bash -c 'f() {( set -e; false; echo hello); }; if f ; then :; fi'
> hello

This seems very wrong, even if it works this way for bash, ksh, and zsh
(the shells I have easy access to). Ick.
(0001135)
ajosey (manager)
2012-02-17 14:39

Reply from Dave Korn (13 Feb 2012):


This behavior has nothing to do with functions. It has to do with the
fact that the 'if' blocks all occurences of set -e. The same behavior would
occur with
    if set -e; false; echo hello; then :; fi
or
    { set -e; false; echo hello;} && echo ok

The only effect of set -e in these cases is to enable the option after the if
or conditional completes whether it was already on or not.

Currently there is no way to enable the behavior of set -e when it is in
the ignored state. I think that this is correct and I don't see the need
for having it do so. I don't like the idea of introducing a new option for
enabling the option immediately since the shell already has so many options.

If this feature is really needed, which I doubt, I would prefer having
set -o errexit do this rather than adding a new name. Then set -o errexit
would be the same as set -e except that it would enable error checking
in the current context even it is in the ignored state.

I doubt whether existing scripts use set -o errexit rather than set -e in
scripts, so I doubt that this change would affect existing scripts.
In any event, I would not change the behavior of set -e which I believe
is correct.

Finally, I assume that for
       f() { set -o errreset; false echo f;}
       { if f;then :;fi; false; echo hello;} && echo ok
the effect of errreset would be to enable set -e for the brace group
as well as for f() so that hello would not be echoed.
(0001138)
Don Cragun (manager)
2012-02-19 01:12

Reply from Chet Ramey (18 Feb 2012)

Sorry I took a while to respond.

I think the concept is not well enough defined (and I see it as a bad idea
even if it is more defined). There are a couple of questions: scope and
side effects.

First, scope. How would the `contexts' be defined (subshells? shell
functions? command substitutions? everywhere -e would cause changes to
be ignored?)? What makes one context a better candidate for this than
another?

Second, side effects. What would enabling -e in a place where it's ignored
mean to the rest of the `enclosing' command? The original request asked
for it to have an effect in shell functions. Say the shell function
returns an error after setting -e, and that function was called as part of
a command list after an `if'. Do we now say that the -e applies to the
rest of that command list, even though it's supposed to be ignored? How
about other commands that are part of the same compound command? Why or
why not?

I see this as something that is not needed or desirable, and whose purpose
can be achieved in many cases by using the `|| return 1' idiom.
(0001144)
Don Cragun (manager)
2012-02-23 16:49

For the reasons noted in Note: 0001135 and Note: 0001138, we do not believe that making the suggested change is appropriate.
(0001146)
melkov (reporter)
2012-02-24 03:59

> Sorry I took a while to respond.
I'm also sorry for my delayed response and thus reopening the issue.

> First, scope. How would the `contexts' be defined
Is "enclosing compound command, subshell, function or the shell" not clear enough?

> Second, side effects.
Using `set -e' inside the troublesome statement was only to illustrate how ridiculous current behavior is. Actual use is of course the -e at the first line of the script.

> Do we now say that the -e applies to the rest of that command list... ?
Of course! `set' command is just a `set' command, wherever it was actually called. No changes required here at all.

> whose purpose can be achieved in many cases by using the `|| return 1' idiom
Users of this idiom do not need -e to begin with.

And a few comments for mr.Korn's response.
I think that it looks more like a response to more recent comments like Note: 0001122 rather than the original change request.

I think that the idea of changing only the errexit option is acceptable, still I assert that no existing scripts rely upon current -e behavior reflected in this issue; instead, existing scripts do mistakenly rely upon behavior I ask for in this change request.
(0001168)
eblake (manager)
2012-03-08 16:59

Without existing implementation practice, this group is unwilling to invent a new requirement. As noted in Note: 0001135 and Note: 0001138, authors of existing compliant shells are reluctant to add this feature.

- Issue History
Date Modified Username Field Change
2012-01-19 01:15 melkov New Issue
2012-01-19 01:15 melkov Status New => Under Review
2012-01-19 01:15 melkov Assigned To => ajosey
2012-01-19 01:15 melkov Name => Alexander Melkov
2012-01-19 01:15 melkov Organization => Yandex
2012-01-19 01:15 melkov Section => 2.14 set
2012-01-19 01:15 melkov Page Number => (page or range of pages)
2012-01-19 01:15 melkov Line Number => (Line or range of lines)
2012-01-19 01:20 melkov Issue Monitored: melkov
2012-01-19 01:23 melkov Note Added: 0001096
2012-01-19 01:43 Don Cragun Page Number (page or range of pages) => 2358
2012-01-19 01:43 Don Cragun Line Number (Line or range of lines) => 74545-74548
2012-01-19 01:43 Don Cragun Interp Status => ---
2012-01-19 02:00 Don Cragun Note Added: 0001097
2012-01-19 02:00 Don Cragun Desired Action Updated
2012-01-19 02:00 Don Cragun Desired Action Updated
2012-01-19 05:06 vkhromov Issue Monitored: vkhromov
2012-01-19 09:38 geoffclare Note Added: 0001098
2012-01-19 09:39 geoffclare Relationship added related to 0000052
2012-01-20 06:38 melkov Note Added: 0001100
2012-01-20 07:32 melkov Note Edited: 0001100
2012-01-20 10:04 geoffclare Note Added: 0001101
2012-02-09 17:05 eblake Note Added: 0001118
2012-02-10 17:43 bkorb Note Added: 0001122
2012-02-17 14:39 ajosey Note Added: 0001135
2012-02-19 01:12 Don Cragun Note Added: 0001138
2012-02-23 16:49 Don Cragun Note Added: 0001144
2012-02-23 16:49 Don Cragun Status Under Review => Closed
2012-02-23 16:49 Don Cragun Resolution Open => Rejected
2012-02-24 03:59 melkov Note Added: 0001146
2012-02-24 03:59 melkov Status Closed => Under Review
2012-02-24 03:59 melkov Resolution Rejected => Reopened
2012-03-08 16:59 eblake Note Added: 0001168
2012-03-08 16:59 eblake Status Under Review => Closed
2012-03-08 16:59 eblake Resolution Reopened => Rejected
2017-10-31 16:43 nico Issue Monitored: nico
2019-02-04 16:07 nick Relationship added parent of 0001168


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker