about summary refs log tree commit diff
path: root/stdlib/exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/exit.c')
-rw-r--r--stdlib/exit.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/stdlib/exit.c b/stdlib/exit.c
index 5166c78044..bbaf138806 100644
--- a/stdlib/exit.c
+++ b/stdlib/exit.c
@@ -132,9 +132,17 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
 }
 
 
+/* The lock handles concurrent exit(), even though the C/POSIX standard states
+   that calling exit() more than once is UB.  The recursive lock allows
+   atexit() handlers or destructors to call exit() itself.  In this case, the
+   handler list execution will resume at the point of the current handler.  */
+__libc_lock_define_initialized_recursive (static, __exit_lock)
+
 void
 exit (int status)
 {
+  /* The exit should never return, so there is no need to unlock it.  */
+  __libc_lock_lock_recursive (__exit_lock);
   __run_exit_handlers (status, &__exit_funcs, true, true);
 }
 libc_hidden_def (exit)