View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000627 | 1003.1(2008)/Issue 7 | Shell and Utilities | public | 2012-10-29 01:39 | 2019-06-10 08:55 |
Reporter | dalias | Assigned To | ajosey | ||
Priority | normal | Severity | Editorial | Type | Clarification Requested |
Status | Closed | Resolution | Accepted As Marked | ||
Name | Rich Felker | ||||
Organization | musl libc | ||||
User Reference | |||||
Section | XSH 2.9.5 Thread Cancellation, system() | ||||
Page Number | unknown | ||||
Line Number | unknown | ||||
Interp Status | Approved | ||||
Final Accepted Text | 0000627:0001419 | ||||
Summary | 0000627: Behavior of system() when cancelled is not specified | ||||
Description | The system() function is specified to be a cancellation point, but as no EINTR error is specified for this function, there is no specification for its side effects when cancelled. The documentation for system() contains a sample implementation in the rationale. This is of course not normative, but if it were, the behavior of system() on cancellation would be to leak a process id (which the application has no way to subsequently wait on) and leave the signal dispositions in a modified state. I doubt this is the intended behavior. The only robust approaches to cancellation of system() that come to my mind are the following: 1. Have system() act on cancellation only if it is already pending before the child process is created. This is definitely safe, but renders its status as a cancellation point mostly useless. 2. Have system() kill and wait on the child before if cancelled, then restore the signal dispositions before invoking the application's cancellation handlers. This seems like the most desirable behavior in most cases, but it could be undesirable if it interrupts an external command in a way that leaves files or other resources in an inconsistent state. 3. Have system() act on cancellation immediately, but guarantee that the child process will be properly waited upon in some implementation-defined manner (e.g. by a new thread created from system's cancellation cleanup handler purely for this purpose). | ||||
Desired Action | Please clarify the intent as to the behavior of system() on cancellation, or that this behavior is implementation-defined. | ||||
Tags | tc2-2008 |
|
Issue 7 at least says system() need not be thread safe. My vote is for 2. The typical use case for thread cancellation is that the user wishes to terminate an operation as quickly as possible. system() should kill the external process with SIGTERM, to give it a chance to clean up. After a grace period, system() then kills the external process with SIGKILL, analog to how shutdown is accomplished. Applications wishing to be immune from this can fork a sub-process from the system() command argument. |
|
"Need not be thread-safe" doesn't preclude using the interface in multi-threaded programs. It just means applications cannot safely use the interface from more than one thread simultaneously. Naturally, making system thread-safe would be a welcome change, especially if C11 does not make any provision for it to be non-thread-safe, but I think that's a separate issue from the one at hand. As for the suggestion in note #0001414 about SIGTERM/SIGKILL, what about just sending SIGTERM? That would make commands killable by default, but would allow the behavior to be overridden by putting an invocation of the trap command at the beginning of the command line. In any case, I think specifying a behavior is probably a topic for the next issue, so perhaps for now it's best to focus on clarifying whether the standard should clarify the current lack of specification and what freedom implementations have, for example whether killing the child process is even conformant behavior. At least one implementation I'm aware of, glibc, presently acts on cancellation by killing the child. |
|
Interpretation response ------------------------ The standard is unclear on this issue, and no conformance distinction can be made between alternative implementations based on this. This is being referred to the sponsor. Rationale: ------------- The system() function is not required to be thread-safe, yet the standard requires a cancellation point to occur when executing it. Notes to the Editor (not part of this interpretation): ------------------------------------------------------- At page 512 line 17704 section 2.9.5.2, remove "system()" from the list of mandatory cancellation points. On page 513-514 lines 17715-17789 section 2.9.5.2, remove all of the following functions (which are not required to be thread-safe) from the list of optional cancellation points: asctime endutxent getopt getutxid catgets ftw getprotobyname getutxline ctime getdate getprotobynumber localtime dbm_close getgrent getprotoent nftw dbm_delete getgrgid getpwent pututxline dbm_fetch getgrnam getpwnam readdir dbm_nextkey gethostent getpwuid setgrent dbm_open getlogin getservbyname setpwent dbm_store getnetbyaddr getservbyport setutxent endgrent getnetbyname getservent strerror endpwent getnetent getutxent ttyname After page 514 line 17789 section 2.9.5.2, add a new paragraph after the list of optional cancellation points: In addition, a cancellation point may occur when a thread is executing any function that this standard does not require to be thread-safe but the implementation documents as being thread-safe. If a thread is cancelled while executing a non-thread-safe function, the behavior is undefined. After page 2072 line 65661 section system(), add a new paragraph to the RATIONALE section: Note also that the above example implementation is not thread-safe. Implementations can provide a thread-safe system() function, but doing so involves complications such as how to restore the signal dispositions for SIGINT and SIGQUIT correctly if there are overlapping calls, and how to deal with cancellation. The example above would not restore the signal dispositions and would leak a process ID if cancelled. This does not matter for a non-thread-safe implementation since cancelling a non-thread-safe function results in undefined behavior (see [xref to 2.9.5.2]). To avoid leaking a process ID, a thread-safe implementation would need to terminate the child process when acting on a cancellation. |
|
Interpretation Proposed 29 Mar 2013 |
|
Interpretation approved 3 May 2013 |
Date Modified | Username | Field | Change |
---|---|---|---|
2012-10-29 01:39 | dalias | New Issue | |
2012-10-29 01:39 | dalias | Status | New => Under Review |
2012-10-29 01:39 | dalias | Assigned To | => ajosey |
2012-10-29 01:39 | dalias | Name | => Rich Felker |
2012-10-29 01:39 | dalias | Organization | => musl libc |
2012-10-29 01:39 | dalias | Section | => XSH 2.9.5 Thread Cancellation, system() |
2012-10-29 01:39 | dalias | Page Number | => unknown |
2012-10-29 01:39 | dalias | Line Number | => unknown |
2012-10-30 11:36 | Konrad_Schwarz | Note Added: 0001414 | |
2012-10-31 04:33 | dalias | Note Added: 0001415 | |
2012-11-08 17:26 | geoffclare | Note Added: 0001419 | |
2012-11-28 16:40 | geoffclare | Note Edited: 0001419 | |
2012-11-28 16:41 | geoffclare | Interp Status | => Pending |
2012-11-28 16:41 | geoffclare | Final Accepted Text | => 0000627:0001419 |
2012-11-28 16:41 | geoffclare | Status | Under Review => Interpretation Required |
2012-11-28 16:41 | geoffclare | Resolution | Open => Accepted As Marked |
2012-11-28 16:42 | geoffclare | Tag Attached: tc2-2008 | |
2013-03-29 08:05 | ajosey | Interp Status | Pending => Proposed |
2013-03-29 08:05 | ajosey | Note Added: 0001519 | |
2013-05-03 12:19 | ajosey | Interp Status | Proposed => Approved |
2013-05-03 12:19 | ajosey | Note Added: 0001576 | |
2019-06-10 08:55 | agadmin | Status | Interpretation Required => Closed |