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.
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”)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,
- except that it may use plain lock-free atomic operations. A plain lock-free atomic operation is an invocation of a function f from Clause 29, such that
f is not a member function, andeither f is the function atomic_is_lock_free(), or for every atomic argument A passed to f, atomic_is_lock_free(A) yields true. All signal handlers shall have C linkage.
The behavior of any function other than a
POFused as a signal handler in a C ++ program is implementation-defined.
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.104.22.168 [numeric.limits.members]:
Add at the end of 18.5p3 [support.start.term]:
Add at the end of 18.5p4 [support.start.term]:
Add at the end of 18.5p10 [support.start.term]:
Clark Nelson provided many useful suggestions, but not necessarily agreement.