The following issue has been SUBMITTED. ====================================================================== https://austingroupbugs.net/view.php?id=1602 ====================================================================== Reported By: kre Assigned To: ====================================================================== Project: Issue 8 drafts Issue ID: 1602 Category: Shell and Utilities Type: Omission Severity: Objection Priority: normal Status: New Name: Robert Elz Organization: User Reference: Section: XCU 2.14 exit XCU 2.14 return Page Number: 2369, 2379 Line Number: 76750, 77069 Final Accepted Text: ====================================================================== Date Submitted: 2022-08-23 16:33 UTC Last Modified: 2022-08-23 16:33 UTC ====================================================================== Summary: No definition of "executed in a trap action" Description: This defect report could also be filed against issue 7 TC2, and probably earlier versions as well, but the wording has changed so much in this area that going back to discuss text which has already been altered seems pointless. Hence filed against draft 2.1.
The wording of exit, when dealing with the case that no specific status to use is given, is: If n is not specified, the result shall be as if n were specified with the current value of the special parameter '?' (see Section 2.5.2), except that when exit is executed in a trap action, the value for the special parameter '?' that is considered ``current'' shall be the value it had immediately preceding the trap action. The wording for return is substantially the same, though the effects, and required interpretation, are different. So, first to consider exit. It seems likely (this requires some guesswork) that the idea here, is that when an EXIT trap (or others, will come to those soon) is executed, if the trap command says just "exit" - which will then cause the shell to terminate, the status it terminates with should be the status that it would have exited with had there been no EXIT trap, and the shell had simply exited. That's fine, understandable, and the way shells have behaved for a long time. Doing the same for other traps is more likely just a "the way we run the trap command is like this, so this is what happens" which is also OK, though for the other traps actually depending upon this for anything is kind of pointless, as the script writer can never know exactly where the script will be when the trap needs to be taken, so the exit status would be more or less random at that point. That all seems good, but it is only meaningful because of the phrase I included above (which is not anywhere in the standard), "which will then cause the shell to terminate". Consider an alternative use of exit: cleanup() { # various stuff not relevant if (cd /somewhere || exit; # cleanup stuff in /somewhere ) then # do some more cleanup stuff else report cleanup failed, manual cleanup required fi } (Ignore the syntax error caused by the ')' being treated as part of what is a comment, that comment would really be code in a real script). and then trap 'echo Finishing; cleanup; exit' EXIT (in which the exit is pointless, but makes for a better discussion). Now assume that the code in the script, sometime later, does "exit 0" That sets the status ($?) to 0, and then runs the EDIT trap before the shell goes away. There's no real question but that the wording in question applies to exit that is in the string passed as the arg to the trap command, but what about the one, executed in a subshell, in the cleanup function. In that one, we may assume that perhaps the function was written long ago, when no traps were being used, and the usage was cleanup; exit 0 that being a pattern (perhaps with different values for the exit status throughout). In that case, it is clear, the exception of being in a trap action does not apply, there is none, and the exit in cleanup returns the status of the the failed cd command (we know it failed, or the exit would not being executed). But then someone decided that it would be cleaner to use an EXIT trap, remove all the calls to cleanup (perhaps there were some exit's in the code, rarely encountered, which had omitted the cleanup, and that bug is being fixed). Now cleanup is being executed in a trap action. That's clear. But is the exit within the subshell within cleanup also "executed in a trap action" or only text that is actually in the trap action string? If were were to decide that it is the latter, then let's assume that instead of just returning, cleanup ended with "exit". That one, not being in a sub-shell, would cause the shell to terminate. But with what status, the status from the last command in cleanup() which is likely what the author of that function intended, or the value of $? that was current when the EXIT trap was taken? We don't know, because nothing in the standard (or nothing I can find) tells us. For return, things get even messier. That's because in general, return is only defined when executed in a function. Simply executing a random "return" in a trap string (like was done with exit) is only meaningful if we caqn guarantee that the trap will only fire while a function is running. That's certainly possible to do, but not all that common. In practice most 'return's that get executed are to return from a function which has just been called. That is func_performed=false func() { if $func_performed; then return; fi # perform whatever the function does func_performed=true } In that func() will return 0 every time, the return will, as $? at that point will be 0, because we know that $func_performed must have been true or the return would not be being executed. Now imagine that func() is called by some tree of function calls, perhaps several times in different circumstanced. The root of that set of functions iis a function done() (not shown here). If we were to now do "trap done INT" what does that mean to that return in func() - it has no impact at all on the final value of $? when the trap action completes (that's controlled by the done() function) and nothing here has any impact at all upon any function that may have been executing when the trap occurred. To do that there would need to be a an explicit "return" in the trap string, anything in any function that is called applies only to that function. Is the return in func() now executed in a trap action, and so required to return whatever status was in $? when the SIGINT trap occurred? That might not have been 0, so (depending upon how func() is used inn unshown code, might alter the execution flow in unexpected ways --- the commented code from func() might even have "return N" for some N != 0, with the intent to alter the flow - but the one shown was not planned to do that. Again, we cannot answer that question, as the standard does not tell us what "executed in a trap action" actually means. Further there have been different interpretations of all of this, it isn't (any longer anyway) simply a case of "well it is obvious, we just didn't write it down" as (some, at least one) shell authors have taken that wording, and actually made their shell do (what is really) absurd things, because of it (when it had previously been sane). There was a thread on the mailing list https://www.mail-archive.com/austin-group-l@opengroup.org/msg06011.html in which this was briefly discussed, but none of the participants in that discussion were people able to actually change the wording. Hence this defect report, to force some attention by those who matter. Desired Action: For exit, it should probably be "an exit command executed while a trap action is being performed, which will cause the shell environment executing the trap action to terminate". That's closer to what might be workable, but even that isn't perfect. Given that exit & return need two quite different definitions, the magic phrase should probably simply be deleted from the standard, and replaced inline by the appropriate definition. ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 2022-08-23 16:33 kre New Issue 2022-08-23 16:33 kre Name => Robert Elz 2022-08-23 16:33 kre Section => XCU 2.14 exit XCU 2.14 return 2022-08-23 16:33 kre Page Number => 2369, 2379 2022-08-23 16:33 kre Line Number => 76750, 77069 ======================================================================