Doc. No.: WG21/P0270R0
Date: 2016-02-12
Author: Hans-J. Boehm
Email: hboehm@google.com

P0270R0: Removing C dependencies from signal handler wording

This topic was briefly addressed on P0063R0, but the authors subsequently decided to address it separately.

The current C++ working draft restricts signal handlers to functions in the intersection of C and C++. We believe this is dubious for at least three reasons:

We propose to remedy this by replacing the notion of a "POF", "plain old function" with a "signal-safe function" defined entirely in C++ terms. The definition we use largely excludes use of the library, thus avoiding any need to reimplement that in a signal-safe manner. This makes the definition rather restrictive. But we believe it remains at least theoretically possible for the user to write very sophisticated signal handlers through the use of atomics.

We expect that, although these changes are clearly substantive, there is no real practical impact. Existing implementations and user code should continue to work unchanged (or remain as broken as they always were.)

We do not exclude lambda expressions from signal handlers, on the assumption that the lambda expression itself should not require memory allocation. We do not say anything about non-function-local statics, since it should not be possible to trigger construction or destruction from within a signal handler.

We somewhat separably propose to make the behavior of non-signal-safe functions in signal handlers undefined, instead of implementation-defined. We are not aware of any implementations that actually attempt to define this.

We do not exclude lambda expressions from signal handlers, on the assumption that the lambda expression itself should not require memory allocation.

The restriction on static intialization warrants discussion. We currently allow even the call of a POF that doesn't access any globals to trigger static initialization (3.6.2p4 [basic.start.init]). It's not clear how to make that work if a thread already part way through the initialization receives the signal. This apears to me to be a preexisting problem that this exposes, rather than a problem introduced by this change.

It may make sense to eventually relax these restrictions invoked through an explicit synchronous raise() call. It's unclear that this is important enough to bother.

These changes are arguably not essential for the adoption of the P0063. But we believe they are highly desirable and should follow P0063 in fairly short order.

Proposed wording changes:

Update 18.10p10 [support.runtime] as follows:

The common subset of the C and C ++ languages consists of all declarations, definitions, and expressions that may appear in a well formed C ++ program and also in a conforming C program. A POF (“plain old function”) signal-safe function" is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, has C linkage, and neither directly nor indirectly:

The behavior of any function other than a POFsignal-safe function used as a signal handler in a C ++ program is implementation-defined undefined.

The signal() function is signal-safe.

We suggest the following additions, partially as examples. We expect that a few other functions should also eventually be declared signal-safe, but these are among the more blatant cases. abort() and quick_exit() are treated as safe by C.

Add after the title of 18.3.2.4 [numeric.limits.members]:

Each member function defined in this section is signal-safe (18.10 [support.runtime]).

Add at the end of 18.5p3 [support.start.term]:

The _Exit() function is signal-safe (18.10 [support.runtime]).

Add at the end of 18.5p4 [support.start.term]:

The abort() function is signal-safe (18.10 [support.runtime]).

Add at the end of 18.5p10 [support.start.term]:

The quick_exit() function is signal-safe (18.10 [support.runtime]). [Note: It may still be unsafe to call from a handler, because the functions registered with at_quick_exit() may not be. --end note]

Acknowledgment

Clark Nelson provided many useful suggestions, but not necessarily agreement.