mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
exit(3): make it thread-safe
It was explained by Rich Felker <dalias@libc.org> 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:
parent
31f688a26d
commit
3f3ec4b99f
2 changed files with 39 additions and 1 deletions
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue