View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001212 | 1003.1(2016/18)/Issue7+TC2 | Shell and Utilities | public | 2018-09-28 02:56 | 2024-06-11 09:08 |
Reporter | kre | Assigned To | |||
Priority | normal | Severity | Objection | Type | Enhancement Request |
Status | Closed | Resolution | Accepted As Marked | ||
Name | Robert Elz | ||||
Organization | |||||
User Reference | |||||
Section | XCU 2.14 -- trap special builtin | ||||
Page Number | 2420 - 2423 | ||||
Line Number | 77484-5 (and more) | ||||
Interp Status | --- | ||||
Final Accepted Text | 0001212:0004358 | ||||
Summary | 0001212: Enhance trap command | ||||
Description | The trap command, as it stands, is missing two useful functions 1) the ability to discover the current action for a particular condition 2) the ability to save the current state of all conditions (see issue 1211) Several shells have implemented a solution to (1) using a new -p option to trap (unfortunately, the output format, and so how it should be used, varies - but at least the mechanism is there). The NetBSD shell has a solution to (2) based upon that for (1), but as far as I know, no other shell has a solution to this, and the NetBSD shell is not in widespread enough use to standardise its mechanism yet. Hence, I am requesting that this issue be marked as "for the future" and retained (along with any notes it attracts, and possible different solutions) until we do have something that is ready to be included in the standard. And implementers - please do *something*... Also note, that for shells that have "trap -p" already, but treat it used with no conditions as identical to "trap" with no operands, that is not a useful feature (two ways to do the same thing) and changing the implementation of "trap -p" as suggested below will do no harm. | ||||
Desired Action | In the SYNOPSIS, between lines 77484 and 77485 add a new form for the command trap -p [condition...] Then somewhere in the DESCRIPTION (probably after the paragraph about trap with no operands, starting on line 77514) add a new paragraph When the -p option is given the trap command shall write, in the same format used when no operands are given, a list of commands for each condition specified as an operand, or if no operands, other than the -p flag, are given, then for all possible conditions for which actions can be set in the shell, whether currently at their default values,or not. It is unspecified whether the values for SIGKILL and SIGSTOP can be obtained this way, but if those are included in trap -p output, the shell shall not object to them used as input provided that the action specified is the same as was, or would be, output by trap -p, and in this case no undefined results shall occur. Then change the example at line 77524 from save_traps=$(trap) to save_traps=$(trap -p) | ||||
Tags | issue8 |
related to | 0001211 | Closed | "trap" (with no args) specification does not match reality |
|
Does it need to be a special case that the output for a trap whose default interpretation as a sigaction is to be ignored, such as SIGCHLD and SIGURG, shall be reported as if they were explicitly set to this if a handler action is not assigned, i.e.: >echo `trap -p CHLD` trap -- "" CHLD and not: trap -- - CHLD or is the first form reported only when an actual trap "" CHLD command has been entered? |
|
Re 0001212:0004356 No, certainly nothing is needed as a special case for signals which default to ignored - those are not the same state in any case - explicitly ignoring a signal is a different state from simply doing nothing, which results in the signal being ignored (perhaps a subtle difference, but a difference nevertheless). I wouldn't use SIGCHLD as an example of that however, as while the effect on signal delivery of an ignored (SIG_IGN) SIGCHLD is the same as for SIGCHLD in its default state (SIG_DFL) being ignored can have other ramifications for the application. This does however raise two other interesting questions. First should the trap command (some enhanced trap command as proposed here) report a signal that was ignored upon entry to the shell as being ignored, or simply as being in its default state? I have no particular insightful answer to that one, and either would be reasonable. My gut tells me that the purpose of the command is to discover what earlier manipulations have been made in the script, so a function (or dot script, or whatever) can return the world to its entry state before finishing. If that's the case the signals ignored on entry (which the shell cannot manipulate anyway) would be irrelevant. However having those signals explicitly listed as ignored would not harm that usage, and would allow the script to discover that no matter how much it wants to receive a SIGxxx it cannot, because its parent invoked it with that signal ignored, and hence the script needs to either fail, or use some other method to handle whatever it needed the signal for (if it was just for synchronisation between its sub-shells, then it might simply pick a different signal to use). My implementation of this currently lists signals that were ignored on entry as being in the default state (or actually, whatever state the script attempted to set the signal into - whether or not that was actually effective) - but that could easily be changed if the overall opinion is that that would be better. This also raises an additional sub-issue of whether or not there should be some method to allow a script to trap a signal that was ignored on entry if it really needs to do that. C programs can do it, I see no particular reason why scripts should not have the option .. the only reason that I can see that it isn't done now, is that typical program behaviour used to be if (signal(SIGxxx, SIG_IGN) != SIG_IGN) signal(SIGxxx, xxx_trap); so that a signal which was ignored would stay that way (that's usually what is wanted) and as sh provided no method to do the test explicitly, so only provided that mechanism. But as it was always OK to restore the signal to its entry state (no test like above is done then) sh always explicitly tests the invocation signal state, as it has no other way to know whether a trap command is establishing a new trap or resetting to the earlier state. If we had the testing method, and an option to not do the test, but simply override an existing SIG_IGN (not previously set by the script) I don't see that it would do any harm - the current trap command would need to continue acting the way it always has of course. The second new issue mentioned above is more specific to SIGCHLD (though could also apply to other signals). If a script does trap '' SIGCHLD and the shell from that actually does signal(SIGCHLD, SIG_IGN) then the shell is not likely to work very well (certainly on some systems). So, the question is, is the shell obliged to actually do what the script instructs, or can it merely act as if it had done that (in this case, by not delivering any SIGCHLD traps to the script). Or on systems where it works this way, is it required that "trap '' SIGCHLD" cause the shell to lose the ability to wait() on any of its children, thus making $? useless for anything not built in? And a corollary to that, if a script does do "trap '' SIGCHLD" the shell then invoke sub-processes (other commands) with SIGCHLD ignored (which most do not expect, and sometimes cannot handle) and in particular if that invoked sub-process is a subshell - either a subshell environment of the current shell, or more relevantly here, "/bin/sh -c 'command || other'" - that sub-process would be invoked with SIGCHLD ignored, and if it is a shell, is it permitted to either set SIGCHLD back to SIG_DFL, or catch the signal (depending upon its needs) or must it comply with the restriction that signals ignored upon entry remain ignored throughout the script? FWIW: the NetBSD shell silently ignores attempts by scripts to manipulate SIGCHLD (or should, but I don't remember if I actually committed that change). Everything appears to the script as if SIGCHLD were trapped/ignored, but no signal() sys call is ever made to affect the kernel when the script does that. It is my intention (not yet implemented) to copy the bash mechanism for this (maybe itself copied from elsewhere) to a degree - and implement script level SIGCHLD traps independent of (and more reliably than) kernel delivered SIGCHLD signals - so that one SIGCHLD trap (in the script) is taken for every asynchronous pipeline (command) that completes (not for every command that completes the way bash implements this - that does not seem to be very useful). In the trap handler $! would be redefined to be the pid of the async job that caused this invocation of the trap handler (so, for example: "wait $!" in the trap handler would clean up the job, and set $? to its status). I believe this is safe, as the trap could fire anywhere in the script, so its handler cannot reasonably be depending upon $! being the pid of any particular last async job started ... unless of course there was only one, in which case, it would be). None of this mechanism is relevant to the standard (certainly not yet) but the question of exactly what the shell is permitted/required to do with signals when implementing the trap command is. |
|
Suggested changes ... In the SYNOPSIS, between lines 77484 and 77485 add a new form for the command trap -p [condition...] On page 2420 line 77487 change: If the first operand is an unsigned decimal integer, the shell shall treat all operands as conditions, and shall reset each condition to the default value. Otherwise, if there are operands, the first is treated as an action and the remaining as conditions.to: If the -p option is not specified and the first operand is an unsigned decimal integer, the shell shall treat all operands as conditions, and shall reset each condition to the default value. Otherwise, if the -p option is not specified and there are operands, the first operand shall be treated as an action and the remaining as conditions. On page 2420 line 77514 after applying bug 1211 change: The trap command with no operands shall write to standard output a list of commands associated with each condition which is not in its default state.to: The trap command with no operands shall write to standard output a list of commands associated with each of a set of conditions; if the -p option is not specified, this set shall contain only the conditions that are not in the default state (including signals that were ignored on entry to a non-interactive shell); if the -p option is specified, the set shall contain all conditions, except that it is unspecified whether conditions corresponding to the SIGKILL and SIGSTOP signals are included in the set. On page 2420 line 77522 after applying bug 1211 change: The shell shall format the output, including the proper use of quoting, so that it is suitable for reinput to the shell as commands that achieve the same trapping results for those traps that had previously been altered.to: The shell shall format the output, including the proper use of quoting, so that it is suitable for reinput to the shell as commands that achieve the same trapping results for the set of conditions included in the output, except for signals that were ignored on entry to the shell as described above. If this set includes conditions corresponding to the SIGKILL and SIGSTOP signals, the shell shall accept them when the output is reinput to the shell (where accepting them means they do not cause a non-zero exit status, a diagnostic message, or undefined behavior). On page 2420 line 77524 after applying bug 1211 change: to:save_traps=$(trap) trap "some command" INT QUIT save_traps="trap - INT QUIT; $save_traps" ... eval "$save_traps" save_traps=$(trap -p) ... eval "$save_traps"or:save_traps=$(trap -p INT QUIT) trap "some command" INT QUIT ... eval "$save_traps" On page 2421 line 77538 change the OPTIONS section from: None.to: The following option shall be supported: On page 2422 line 77564 after applying bug 1211 change APPLICATION USAGE to: When the -p option is not used, since trap with no operands does not output commands to restore traps that are currently set to default, these need to be restored separately. The RATIONALE section shows examples and describes their drawbacks. On page 2423 line 77604 add some new paragraphs to RATIONALE: The -p option was added because without it the method used to restore traps needs to include special handling of traps that are set to default when trap with no operands is used to save the current traps. One example is:save_traps=$(trap) trap "some command" INT QUIT save_traps="trap - INT QUIT; $save_traps" ... eval "$save_traps"but this method relies on hard-coding the commands to reset the traps that are being set. It also has a race condition if INT or QUIT was not set to default when saved, since it first sets them to default and then restores the saved traps. A more general approach would be:save_traps=$(trap) ... for sig in EXIT $( kill -l ) do case "$sig" in SIGKILL | KILL | sigkill | kill | SIGSTOP | STOP | sigstop | stop) ;; *) trap - $sig ;; esac done eval "$save_traps"This has the same race condition since it first sets all traps (that can be set) to default and then restores those that were not previously set to default. On page 2423 line 77606 revert the bug 1211 change, so that FUTURE DIRECTIONS is: None. |
|
Hi Geoff, your text does not include an explanation on what should happen with e.g. trap -p INT .... The easy way to implement -p results in -p being ignored in such a case and the SIGINT trap restored to it's default. If you like to require that "trap -p INT" lists the trap state for SIGINT, I would need to restructure the trap implementation in the Bourne Shell. Also: The requirement to print the state of "ignored since startup" traps without -p is a change compared to the historic behavior and I tend not to change this behavior. |
|
In the proposed change on page 2420 line 77522 after applying bug 1211 change:
I believe it is incorrect to say "shall silently ignore" here. Many shells permit a trap of these signals, even though they cannot be caught or ignored. When you request a list of currently set traps, that (meaningless) action is listed. So the shell does not ignore the setting ... it is doing something with it. It is ignoring the error that occurs should it call signal() or sigaction() on these signals. The important thing is that the list produced by trap -p can be re-input without an error being reported, so you don't need to filter out those uncatchable signals from the list. So I believe it would be better to replace "the shell shall silently ignore them" with "the shell shall not produce any diagnostic message with respect to these signals", leaving it unspecified as to what else it might or might not do. |
|
Re: 4359 Doesn't `trap -p INT' fall under the first sentence of the -p description? "Write to standard output a list of commands associated with each condition operand" |
Date Modified | Username | Field | Change |
---|---|---|---|
2018-09-28 02:56 | kre | New Issue | |
2018-09-28 02:56 | kre | Name | => Robert Elz |
2018-09-28 02:56 | kre | Section | => XCU 2.14 -- trap special builtin |
2018-09-28 02:56 | kre | Page Number | => 2420 - 2423 |
2018-09-28 02:56 | kre | Line Number | => 77484-5 (and more) |
2019-04-04 17:35 | shware_systems | Note Added: 0004356 | |
2019-04-06 07:54 | kre | Note Added: 0004357 | |
2019-04-09 11:07 | geoffclare | Note Added: 0004358 | |
2019-04-09 11:09 | geoffclare | Note Edited: 0004358 | |
2019-04-09 11:11 | geoffclare | Note Edited: 0004358 | |
2019-04-09 11:13 | geoffclare | Note Edited: 0004358 | |
2019-04-09 11:19 | geoffclare | Relationship added | related to 0001211 |
2019-04-09 13:32 | joerg | Note Added: 0004359 | |
2019-04-09 13:35 | joerg | Note Edited: 0004359 | |
2019-04-09 13:52 | geoffclare | Note Edited: 0004358 | |
2019-04-09 14:27 | nick | Note Added: 0004360 | |
2019-04-10 08:33 | geoffclare | Note Edited: 0004358 | |
2019-04-11 15:33 | geoffclare | Note Edited: 0004358 | |
2019-04-11 15:48 | geoffclare | Interp Status | => --- |
2019-04-11 15:48 | geoffclare | Final Accepted Text | => 0001212:0004358 |
2019-04-11 15:48 | geoffclare | Status | New => Resolved |
2019-04-11 15:48 | geoffclare | Resolution | Open => Accepted As Marked |
2019-04-11 15:48 | geoffclare | Tag Attached: issue8 | |
2019-04-15 14:23 | chet_ramey | Note Added: 0004361 | |
2020-04-27 11:18 | geoffclare | Status | Resolved => Applied |
2024-06-11 09:08 | agadmin | Status | Applied => Closed |