about summary refs log tree commit diff
path: root/src/exit/atexit.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-10-14 23:21:54 -0400
committerRich Felker <dalias@aerifal.cx>2011-10-14 23:21:54 -0400
commitb7c683be35586f671d91c9883c9a41920938df9b (patch)
treedeba5d24ca3cfe368e824c1ee2b56665ea01ebc4 /src/exit/atexit.c
parentf753049a50132a23849ef89a8af5ff86ad595c25 (diff)
downloadmusl-b7c683be35586f671d91c9883c9a41920938df9b.tar.gz
musl-b7c683be35586f671d91c9883c9a41920938df9b.tar.xz
musl-b7c683be35586f671d91c9883c9a41920938df9b.zip
support __cxa_atexit, and registering atexit functions from atexit handlers
mildly tested; may have bugs. the locking should be updated not to use
spinlocks but that's outside the scope of this one module.
Diffstat (limited to 'src/exit/atexit.c')
-rw-r--r--src/exit/atexit.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/src/exit/atexit.c b/src/exit/atexit.c
index 6f00e374..c613d85b 100644
--- a/src/exit/atexit.c
+++ b/src/exit/atexit.c
@@ -1,5 +1,6 @@
 #include <stddef.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <limits.h>
 #include "libc.h"
 
@@ -9,26 +10,33 @@
 static struct fl
 {
 	struct fl *next;
-	void (*f[COUNT])(void);
+	void (*f[COUNT])(void *);
+	void *a[COUNT];
 } builtin, *head;
 
+static int lock;
+
 void __funcs_on_exit()
 {
 	int i;
+	void (*func)(void *), *arg;
+	LOCK(&lock);
 	for (; head; head=head->next) {
 		for (i=COUNT-1; i>=0 && !head->f[i]; i--);
-		for (; i>=0; i--) head->f[i]();
+		if (i<0) continue;
+		func = head->f[i];
+		arg = head->a[i];
+		head->f[i] = 0;
+		UNLOCK(&lock);
+		func(arg);
+		LOCK(&lock);
 	}
 }
 
-int atexit(void (*func)(void))
+int __cxa_atexit(void (*func)(void *), void *arg, void *dso)
 {
-	static int lock;
 	int i;
 
-	/* Hook for atexit extensions */
-	if (libc.atexit) return libc.atexit(func);
-
 	LOCK(&lock);
 
 	/* Defer initialization of head so it can be in BSS */
@@ -48,7 +56,18 @@ int atexit(void (*func)(void))
 	/* Append function to the list. */
 	for (i=0; i<COUNT && head->f[i]; i++);
 	head->f[i] = func;
+	head->a[i] = arg;
 
 	UNLOCK(&lock);
 	return 0;
 }
+
+static void call(void *p)
+{
+	((void (*)(void))(uintptr_t)p)();
+}
+
+int atexit(void (*func)(void))
+{
+	return __cxa_atexit(call, (void *)(uintptr_t)func, 0);
+}