Skip to content

Commit

Permalink
exit(3): make it thread-safe
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kostikbel committed Jul 29, 2024
1 parent 31f688a commit 3f3ec4b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
19 changes: 18 additions & 1 deletion lib/libc/stdlib/exit.3
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions lib/libc/stdlib/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "namespace.h"
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "un-namespace.h"

Expand All @@ -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.
*/
Expand All @@ -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.
Expand Down

0 comments on commit 3f3ec4b

Please sign in to comment.