summaryrefslogtreecommitdiff
path: root/src/exit/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exit/exit.c')
-rw-r--r--src/exit/exit.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/exit/exit.c b/src/exit/exit.c
index a6869b37..ca11b9ad 100644
--- a/src/exit/exit.c
+++ b/src/exit/exit.c
@@ -1,6 +1,9 @@
#include <stdlib.h>
#include <stdint.h>
#include "libc.h"
+#include "pthread_impl.h"
+#include "atomic.h"
+#include "syscall.h"
static void dummy()
{
@@ -26,6 +29,17 @@ weak_alias(libc_exit_fini, __libc_exit_fini);
_Noreturn void exit(int code)
{
+ /* Handle potentially concurrent or recursive calls to exit,
+ * whose behaviors have traditionally been undefined by the
+ * standards. Using a custom lock here avoids pulling in lock
+ * machinery and lets us trap recursive calls while supporting
+ * multiple threads contending to be the one to exit(). */
+ static volatile int exit_lock[1];
+ int tid = __pthread_self()->tid;
+ int prev = a_cas(exit_lock, 0, tid);
+ if (prev == tid) a_crash();
+ else if (prev) for (;;) __syscall(SYS_pause);
+
__funcs_on_exit();
__libc_exit_fini();
__stdio_exit();