|Anonymous | Login||2023-12-07 10:46 UTC|
|Main | My View | View Issues | Change Log | Docs|
|Viewing Issue Simple Details|
|ID||Category||Severity||Type||Date Submitted||Last Update|
|0000728||[1003.1(2013)/Issue7+TC1] System Interfaces||Editorial||Clarification Requested||2013-08-05 15:16||2023-09-04 10:21|
|Priority||normal||Resolution||Accepted As Marked|
|Section||XSH 2.4.3 Signal Actions|
|Final Accepted Text||Note: 0006430|
|Summary||0000728: Restrictions on signal handlers are both excessive and insufficient|
Per XSH 2.4.3:
"the behavior is undefined if the signal handler refers to any object other than errno with static storage duration other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than one of the functions listed in the following table."
The intent here is that signal handlers cannot access objects which might be in a partially-modified state when the (asynchronous) signal handler is invoked. However, this is not what it says. Consider for example a program which allocates an object via malloc (or with automatic storage in main()) and stores the address in /tmp/foo. Per the language of the standard, the signal handler can legitimately open /tmp/foo (open is AS-safe), read that address (read is AS-safe), and dereference the pointer, even though the object may be in a partially-modified state.
As a second example, one can arrange for the address of such an object to be delivered to the signal handler via the sigval argument to realtime signals, timers, etc. and in fact using these features generally REQUIRES a pointer to be delivered to the signal handler.
Moreover, plenty of legitimate accesses to objects with static storage duration is wrongly forbidden:
- Access to const-qualified objects.
- Access to string literals (note in the above example, a string literal could not be passed to open; instead, the array "/dev/tmp" must be automatic).
- Access to a modifiable object of static storage duration whose last modification was sequenced before the signal handler could have been invoked via sigprocmask(), pthread_sigmask(), sigaction(), etc.
There is no reason to forbid such accesses, and to my knowledge there is no historical implementation for which they would not work.
This issue report is partly inspired by: http://www.tedunangst.com/flak/post/signal-safe-strcpy [^]
Ideally, replace the restriction on access to static objects in XSH 2.4.3 with a proper memory model for access to objects (static or otherwise) from signal handlers based on sequencing by signal masking or other means.
Alternatively, require that no object except objects with automatic storage duration whose lifetimes began within the signal handling context be accessed from within the signal handling context. In my opinion, this would be excessively restrictive, but at least it would close the loophole/inconsistency in the existing language where access to static objects is forbidden but access to dynamic or automatic objects that exist outside the signal handler is permitted.
|Additionally, no restrictions on access to objects should apply when a synchronous signal is being handled (e.g. SIGPIPE) unless the invocation was a result of undefined behavior (in which case, the standard has nothing to say, anyway).|
Some thoughts on how the memory model should work:
Access to an object which is modified by another thread without synchronization has undefined behavior [same as always; signal handlers are not special here].
Access to an object which is modified in the same thread as the signal handler runs in has undefined behavior unless one of the following conditions is met:
1. Access is sequenced by controlling the signal mask or signal disposition [or possibly other means yet to be determined; formally supporting the "self-pipe trick" would be desirable at least] so as to establish an ordering relation between the accesses from the interrupted thread and the signal handler.
2. The object has type sig_atomic_t or character type. [I included character types along with sig_atomic_t because the C11 memory model essentially requires byte-granularity writes to be supported by the hardware. If this is objectionable, it could be omitted, but I think it is the correct direction for the future.]
|There is a small omission in note 0001838 (my previous note on this issue): under condition 2, "The object has type sig_atomic_t or character type." should instead read "The object is volatile-qualified and has type sig_atomic_t or character type."|
In the January 2023 ballot resolution meeting, WG14 decided not to make any change to the signal handler requirements in C23. This means we are free to change this as we please (with CX shading) without worrying about the potential for a mis-match with an equivalent change in C23.
A useful piece of feedback from them is that we need to be careful about the phrase "const-qualified objects". If a modifiable object of type T is accessed via a pointer to const T, this could be interpreted as accessing a const-qualified object, but obviously should not be allowed. I suggest the text should say that access to "non-modifiable objects" is allowed and give as examples: string literals, objects that were defined with a const-qualified type, and objects in memory that was mapped read-only.
Issue 8 will have the definition of "happens before" from C17, so we could use that to add something about sequencing. Perhaps something along the lines of "the previous modification (if any) to the object happens before the signal handler is called and the return from the signal handler happens before the next modification (if any) to the object".
Note that there will be changes in this area in draft 3 (talking about lock-free atomic objects) so we should wait for draft 3 before working on wording changes.
On Issue 8 draft 3 page 516 line 18330 section 2.4.3, change:
the behavior is undefined if the signal handler refers to any object other than errno with static or thread storage duration that is not a lock-free atomic object, other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function or function-like macro defined in this standard other than one of the functions and macros specified below as being async-signal-safe.to:
the behavior is undefined if:
On Issue 8 draft 3 page 2049 line 67324 section signal(), change:
the behavior is undefined if the signal handler refers to any object [CX]other than errno[/CX] with static or thread storage duration that is not a lock-free atomic object, other than by assigning a value to an object declared as volatile sig_atomic_t, or if the signal handler calls any function defined in this standard other than [CX]one of the functions listed in Section 2.4 (on page 511)[/CX].to:
the behavior is undefined if:
|2013-08-05 15:16||dalias||New Issue|
|2013-08-05 15:16||dalias||Name||=> Rich Felker|
|2013-08-05 15:16||dalias||Organization||=> musl libc|
|2013-08-05 15:16||dalias||Section||=> XSH 2.4.3 Signal Actions|
|2013-08-05 15:16||dalias||Page Number||=> unknown|
|2013-08-05 15:16||dalias||Line Number||=> unknown|
|2013-08-05 15:18||dalias||Note Added: 0001699|
|2013-08-15 15:36||eblake||Relationship added||related to 0000733|
|2013-09-20 18:05||dalias||Note Added: 0001838|
|2013-09-20 18:17||eadler||Issue Monitored: eadler|
|2013-10-07 22:43||dalias||Note Added: 0001863|
|2023-01-26 10:46||geoffclare||Note Added: 0006138|
|2023-08-14 15:57||geoffclare||Note Added: 0006430|
|2023-08-14 15:58||geoffclare||Interp Status||=> ---|
|2023-08-14 15:58||geoffclare||Final Accepted Text||=> Note: 0006430|
|2023-08-14 15:58||geoffclare||Status||New => Resolved|
|2023-08-14 15:58||geoffclare||Resolution||Open => Accepted As Marked|
|2023-08-14 15:58||geoffclare||Tag Attached: issue8|
|2023-09-04 10:21||geoffclare||Status||Resolved => Applied|
|2023-09-04 10:21||geoffclare||Tag Attached: applied_after_i8d3|
|Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group|