summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/stdlib/atexit.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 95047e78f..d3632c276 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -29,12 +29,29 @@
* As a side effect of these changes, abort() no longer calls the exit
* functions (it now matches the gnu libc definition).
*
+ * August 2002 Erik Andersen
+ * Added locking so atexit and friends can be thread safe
+ *
*/
+#define _GNU_SOURCE
+#include <features.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
+
+#ifdef __UCLIBC_HAS_THREADS__
+#include <pthread.h>
+static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+# define LOCK pthread_mutex_lock(&mylock)
+# define UNLOCK pthread_mutex_unlock(&mylock);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+
#define __MAX_EXIT __UCLIBC_MAX_ATEXIT
typedef void (*aefuncp) (void); /* atexit function pointer */
@@ -70,7 +87,9 @@ int atexit(aefuncp func)
{
struct exit_function *efp;
+ LOCK;
if (__exit_count >= __MAX_EXIT) {
+ UNLOCK;
__set_errno(ENOMEM);
return -1;
}
@@ -80,6 +99,7 @@ int atexit(aefuncp func)
efp->type = ef_atexit;
efp->funcs.atexit = func;
}
+ UNLOCK;
return 0;
}
#endif
@@ -95,7 +115,9 @@ int on_exit(oefuncp func, void *arg)
{
struct exit_function *efp;
+ LOCK;
if (__exit_count >= __MAX_EXIT) {
+ UNLOCK;
__set_errno(ENOMEM);
return -1;
}
@@ -106,6 +128,7 @@ int on_exit(oefuncp func, void *arg)
efp->funcs.on_exit.func = func;
efp->funcs.on_exit.arg = arg;
}
+ UNLOCK;
return 0;
}
#endif
@@ -116,6 +139,8 @@ int __exit_count = 0; /* Number of registered exit functions */
/*
* Handle the work of executing the registered exit functions
+ * This is called while we are locked, so no additional locking
+ * is needed...
*/
void __exit_handler(int status)
{
@@ -150,9 +175,11 @@ void (*__exit_cleanup) (int) = 0;
void exit(int rv)
{
/* Perform exit-specific cleanup (atexit and on_exit) */
+ LOCK;
if (__exit_cleanup) {
__exit_cleanup(rv);
}
+ UNLOCK;
/* If we are using stdio, try to shut it down. At the very least,
* this will attempt to commit all buffered writes. It may also