summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exit/atexit.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/exit/atexit.c b/src/exit/atexit.c
index 854e9fdd..92c91c9d 100644
--- a/src/exit/atexit.c
+++ b/src/exit/atexit.c
@@ -19,6 +19,7 @@ static struct fl
void *a[COUNT];
} builtin, *head;
+static int finished_atexit;
static int slot;
static volatile int lock[1];
volatile int *const __atexit_lockptr = lock;
@@ -34,6 +35,10 @@ void __funcs_on_exit()
func(arg);
LOCK(lock);
}
+ /* Unlock to prevent deadlock if a global dtor
+ * attempts to call atexit. */
+ finished_atexit = 1;
+ UNLOCK(lock);
}
void __cxa_finalize(void *dso)
@@ -44,6 +49,13 @@ int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
{
LOCK(lock);
+ /* Prevent dtors from registering further atexit
+ * handlers that would never be run. */
+ if (finished_atexit) {
+ UNLOCK(lock);
+ return -1;
+ }
+
/* Defer initialization of head so it can be in BSS */
if (!head) head = &builtin;