|Anonymous | Login||2023-03-21 04:59 UTC|
|Main | My View | View Issues | Change Log | Docs|
|Viewing Issue Simple Details [ Jump to Notes ]||[ Issue History ] [ Print ]|
|ID||Category||Severity||Type||Date Submitted||Last Update|
|0000851||[1003.1(2013)/Issue7+TC1] System Interfaces||Comment||Omission||2014-06-26 23:34||2022-08-19 15:02|
|Priority||normal||Resolution||Accepted As Marked|
|Section||(section number or name, can be interface name)|
|Page Number||(page or range of pages)|
|Line Number||(Line or range of lines)|
|Final Accepted Text||Note: 0005915|
|Summary||0000851: pthread_atfork orphans handlers in unloaded shared libraries|
|Description||pthread_atfork is used to register functions to be called before and after a fork operation. The intent of the facility is to ensure that the child receives consistent copies of mutexes and other pieces of shared state. If a process loads a shared library, registers pthread_atfork handlers for that library, then unloads the library, the process will likely segfault the next time it calls fork. Some implementations automatically unregister handlers in this scenario, but there is no requirement to do so, and many implementations malfunction in the way described above.|
|Desired Action||Please either requirement dlclose to automatically unregister pthread_atfork handlers or provide an explicit interface for unregistering these handlers manually. I would prefer the explicit interface.|
|The standard is already clear that pthread_atfork cannot usefully be used in multithreaded programs. "As explained, there is no suitable solution for functionality which requires non-atomic operations to be protected through mutexes and locks. This is why the POSIX.1 standard since the 1996 release requires that the child process after fork( ) in a multi-threaded process only calls async-signal-safe interfaces." (line 50303). Given that, is there any really reason to try and extend the requirements of an already broken-by-design interface?|
edited on: 2014-07-11 14:33
I don't think the standard currently does enough to warn application writers of the dangers of using this function. In addition to any change relating to dlclose() I would suggest making the following changes:
After line 50230 add a new paragraph:
If a fork() call in a multi-threaded process leads to a child fork handler calling any function that is not async-signal-safe, the behavior is undefined.
On line 50244 change the APPLICATION USAGE section from:
The original usage pattern envisaged for pthread_atfork() was for the prepare fork handler to lock mutexes and other locks, and for the parent and child handlers to unlock them. However, since all of the relevant unlocking functions are not async-signal-safe this usage results in undefined behavior in the child process.
On page 889 line 29741 section fork() delete:
Fork handlers may be established by means of the pthread_atfork() function in order to maintain application invariants across fork() calls.
[Update: these changes are now the subject of a separate bug: 0000858]
Regarding: "However, since all of the relevant unlocking functions are not async-signal-safe this usage results in undefined behavior in the child process."
This statement is not entirely true: sem_post is async-signal-safe. It's not clear to me whether the copy of a semaphore which exists in the child after fork is a valid argument for sem_post, but perhaps the issue should be clarified, since sem_post provides a seemingly-plausible way to use pthread_atfork while avoiding the design flaw.
|Is there existing practice for unregistering pthread_atfork() callbacks? Also, should we add the ability to unregister an atexit() callback?|
There is existing practice in Solaris to auto-unregister functions for various
callbacks in case that dlclose() has been called for a library that contains
such a callback function.
|Perhaps dlclose should be required either to unregister such handlers when unloading the library, or to refuse to unload any library for which such handlers have been registered. This would leave some flexibility with the implementation while ensuring that handlers which are no longer loaded do not get called.|
The current (2016/2018) standard has this in the pthread_atfork() FUTURE DIRECTIONS:
The pthread_atfork() function may be formally deprecated (for example, by shading it OB) in a future version of this standard.
It does not seem reasonable to place additional requirements on implementations for a function that is planned to be removed from the standard at some point. So I suggest we should go ahead and shade the function OB in Issue 8 and just document the library unloading problem in APPLICATION USAGE (or RATIONALE).
On 2018 edition page 315 line 10683 section <pthread.h> add OB shading to pthread_atfork().
On 2018 edition page 1560 line 51088-51090 add OB shading to pthread_atfork() SYNOPSIS.
On 2018 edition page 1562 line 51179 add to pthread_atfork() RATIONALE:
An additional problem arises when pthread_atfork() is called to register a function in a library that was loaded using dlopen(). If the library is unloaded using dlclose(), and the implementation of dlclose() does not unregister the function, then when fork() tries to call it the result will be undefined behavior. Some implementations of dlclose() do unregister pthread_atfork() handlers, but this cannot be relied upon by portable applications. The standard provides no portable method for unregistering a function installed as a handler via pthread_atfork().
On 2018 edition page 1562 line 51181 change pthread_atfork() FUTURE DIRECTIONS to:
The pthread_atfork( ) function may be removed in a future version of this standard.
|2014-06-26 23:34||dancol||New Issue|
|2014-06-26 23:34||dancol||Name||=> Daniel Colascione|
|2014-06-26 23:34||dancol||Section||=> (section number or name, can be interface name)|
|2014-06-26 23:34||dancol||Page Number||=> (page or range of pages)|
|2014-06-26 23:34||dancol||Line Number||=> (Line or range of lines)|
|2014-06-27 01:09||eblake||Note Added: 0002286|
|2014-06-27 09:32||geoffclare||Note Added: 0002287|
|2014-06-27 14:43||dalias||Note Added: 0002291|
|2014-07-10 16:07||eblake||Note Added: 0002307|
|2014-07-11 14:33||geoffclare||Note Edited: 0002287|
|2014-07-17 15:08||joerg||Note Added: 0002309|
|2014-07-17 16:18||dalias||Note Added: 0002310|
|2022-07-26 11:12||geoffclare||Note Added: 0005912|
|2022-07-28 15:37||geoffclare||Note Added: 0005915|
|2022-07-28 15:38||geoffclare||Interp Status||=> ---|
|2022-07-28 15:38||geoffclare||Final Accepted Text||=> Note: 0005915|
|2022-07-28 15:38||geoffclare||Status||New => Resolved|
|2022-07-28 15:38||geoffclare||Resolution||Open => Accepted As Marked|
|2022-07-28 15:39||geoffclare||Tag Attached: tc3-2008|
|2022-07-28 15:54||eblake||Relationship added||related to 0000858|
|2022-08-19 15:02||geoffclare||Status||Resolved => Applied|
|Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group|