mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
exit(3): make it thread-safe
It was explained by Rich Felker <[email protected]> on libc-coord. See https://austingroupbugs.net/view.php?id=1845. Reviewed by: imp, markj Tested by: antoine (exp-run) Sponsored by: The FreeBSD Foundation MFC after: 1 month Differential revision: https://reviews.freebsd.org/D46108
This commit is contained in:
1 parent
31f688a26d
commit
3f3ec4b99f
2 files changed
+39
-1
No files matched your search
+18
-1
@@ -29,7 +29,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 5, 2021
|
||||
.Dd July 24, 2024
|
||||
.Dt EXIT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -102,6 +102,23 @@ values described in
|
||||
.Xr sysexits 3
|
||||
may be used to provide more information to the parent process.
|
||||
.Pp
|
||||
Calls to the
|
||||
.Fn exit
|
||||
function are serialized.
|
||||
All functions registered by
|
||||
.Xr atexit 3
|
||||
are executed in the first thread that called
|
||||
.Nm exit .
|
||||
If any other thread of the process calls
|
||||
.Nm exit
|
||||
before all registered functions have completed or before the process
|
||||
terminates, the thread is blocked until the process terminates.
|
||||
The exit status of the process is the
|
||||
.Fa status
|
||||
argument of the first
|
||||
.Nm exit
|
||||
call which thread proceeds the atexit handlers.
|
||||
.Pp
|
||||
Note that
|
||||
.Fn exit
|
||||
does nothing to prevent bottomless recursion should a function registered
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "namespace.h"
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
@@ -48,6 +49,20 @@ void (*__cleanup)(void);
|
||||
*/
|
||||
int __isthreaded = 0;
|
||||
|
||||
static pthread_mutex_t exit_mutex;
|
||||
static pthread_once_t exit_mutex_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void
|
||||
exit_mutex_init_once(void)
|
||||
{
|
||||
pthread_mutexattr_t ma;
|
||||
|
||||
_pthread_mutexattr_init(&ma);
|
||||
_pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
|
||||
_pthread_mutex_init(&exit_mutex, &ma);
|
||||
_pthread_mutexattr_destroy(&ma);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit, flushing stdio buffers if necessary.
|
||||
*/
|
||||
@@ -59,6 +74,12 @@ exit(int status)
|
||||
|
||||
_thread_autoinit_dummy_decl = 1;
|
||||
|
||||
/* Make exit(3) thread-safe */
|
||||
if (__isthreaded) {
|
||||
_once(&exit_mutex_once, exit_mutex_init_once);
|
||||
_pthread_mutex_lock(&exit_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* We're dealing with cleaning up thread_local destructors in the case of
|
||||
* the process termination through main() exit.
|
||||
|
||||
Reference in new issue
Block a user