Anonymous | Login | 2023-11-29 18:48 UTC |
Main | My View | View Issues | Change Log | Docs |
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 | |||||||
|
![]() |
|||||||||||
|
![]() |
|
(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. |
Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group |