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
0000627 [1003.1(2008)/Issue 7] Shell and Utilities Editorial Clarification Requested 2012-10-29 01:39 2019-06-10 08:55
Reporter dalias View Status public  
Assigned To ajosey
Priority normal Resolution Accepted As Marked  
Status Closed  
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 Note: 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
Attached Files

- Relationships

-  Notes
Konrad_Schwarz (reporter)
2012-10-30 11:36

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.
dalias (reporter)
2012-10-31 04:33

"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.
geoffclare (manager)
2012-11-08 17:26
edited on: 2012-11-28 16:40

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.

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, remove "system()" from the
list of mandatory cancellation points.

On page 513-514 lines 17715-17789 section, 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, 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]). To avoid leaking a process ID, a
    thread-safe implementation would need to terminate the child
    process when acting on a cancellation.

ajosey (manager)
2013-03-29 08:05

Interpretation Proposed 29 Mar 2013
ajosey (manager)
2013-05-03 12:19

Interpretation approved 3 May 2013

- Issue History
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 => Note: 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

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