summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-11-19 07:08:33 +0000
committerEric Andersen <andersen@codepoet.org>2002-11-19 07:08:33 +0000
commit336849ea6e8dc302f7e77aeabadd8961f9666bfb (patch)
tree440119eef03b58c7e46742d802e2289f2d52f134
parenta0f9833ef7bf9dafa258ac30329223b5d1022965 (diff)
Implement dynamic atexit handling. Adds a few bytes and a dependancy
on malloc (via realloc). -Erik
-rw-r--r--extra/Configs/Config.in17
-rw-r--r--libc/stdlib/atexit.c96
2 files changed, 85 insertions, 28 deletions
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 7bba49995..99f60dfff 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -89,6 +89,23 @@ config MALLOC_930716
endchoice
+config UCLIBC_DYNAMIC_ATEXIT
+ bool "Dynamic atexit() Support"
+ default y
+ help
+
+ When this option is enabled, uClibc will support an infinite number,
+ of atexit() and on_exit() functions, limited only by your available
+ memory. This can be important when uClibc is used with C++, since
+ global destructors are implemented via atexit(), and it is quite
+ possible to exceed the default number when this option is disabled.
+ Enabling this option adds a few bytes, and more significantly makes
+ atexit and on_exit depend on malloc, which can be bad when compiling
+ static executables.
+
+ Unless you use uClibc with C++, you should probably answer N.
+
+
config HAS_SHADOW
bool "Shadow Password Support"
default y
diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c
index 44abc343b..e82f53fe3 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -52,8 +52,6 @@ extern pthread_mutex_t mylock;
#endif
-#define __MAX_EXIT __UCLIBC_MAX_ATEXIT
-
typedef void (*aefuncp) (void); /* atexit function pointer */
typedef void (*oefuncp) (int, void *); /* on_exit function pointer */
typedef enum {
@@ -65,9 +63,10 @@ typedef enum {
extern void (*__exit_cleanup) (int);
/* these are in the L___do_exit object */
+extern int __exit_slots;
extern int __exit_count;
extern void __exit_handler(int);
-extern struct exit_function {
+struct exit_function {
ef_type type; /* ef_atexit or ef_on_exit */
union {
aefuncp atexit;
@@ -76,7 +75,12 @@ extern struct exit_function {
void *arg;
} on_exit;
} funcs;
-} __exit_function_table[__MAX_EXIT];
+};
+#ifdef __UCLIBC_DYNAMIC_ATEXIT__
+extern struct exit_function *__exit_function_table;
+#else
+extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT];
+#endif
#ifdef L_atexit
/*
@@ -85,22 +89,34 @@ extern struct exit_function {
*/
int atexit(aefuncp func)
{
- struct exit_function *efp;
-
- LOCK;
- if (__exit_count >= __MAX_EXIT) {
+ struct exit_function *efp;
+
+ LOCK;
+ if (func) {
+#ifdef __UCLIBC_DYNAMIC_ATEXIT__
+ /* If we are out of function table slots, make some more */
+ if (__exit_slots < __exit_count+1) {
+ __exit_function_table=realloc(__exit_function_table, __exit_slots+20);
+ if (__exit_function_table==NULL) {
UNLOCK;
__set_errno(ENOMEM);
return -1;
+ }
}
- if (func) {
- __exit_cleanup = __exit_handler; /* enable cleanup */
- efp = &__exit_function_table[__exit_count++];
- efp->type = ef_atexit;
- efp->funcs.atexit = func;
+#else
+ if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
+ UNLOCK;
+ __set_errno(ENOMEM);
+ return -1;
}
- UNLOCK;
- return 0;
+#endif
+ __exit_cleanup = __exit_handler; /* enable cleanup */
+ efp = &__exit_function_table[__exit_count++];
+ efp->type = ef_atexit;
+ efp->funcs.atexit = func;
+ }
+ UNLOCK;
+ return 0;
}
#endif
@@ -113,29 +129,48 @@ int atexit(aefuncp func)
*/
int on_exit(oefuncp func, void *arg)
{
- struct exit_function *efp;
-
- LOCK;
- if (__exit_count >= __MAX_EXIT) {
+ struct exit_function *efp;
+
+ LOCK;
+ if (func) {
+#ifdef __UCLIBC_DYNAMIC_ATEXIT__
+ /* If we are out of function table slots, make some more */
+ if (__exit_slots < __exit_count+1) {
+ __exit_function_table=realloc(__exit_function_table, __exit_slots+20);
+ if (__exit_function_table==NULL) {
UNLOCK;
__set_errno(ENOMEM);
return -1;
+ }
}
- if (func) {
- __exit_cleanup = __exit_handler; /* enable cleanup */
- efp = &__exit_function_table[__exit_count++];
- efp->type = ef_on_exit;
- efp->funcs.on_exit.func = func;
- efp->funcs.on_exit.arg = arg;
+#else
+ if (__exit_count >= __UCLIBC_MAX_ATEXIT) {
+ UNLOCK;
+ __set_errno(ENOMEM);
+ return -1;
}
- UNLOCK;
- return 0;
+#endif
+
+ __exit_cleanup = __exit_handler; /* enable cleanup */
+ efp = &__exit_function_table[__exit_count++];
+ efp->type = ef_on_exit;
+ efp->funcs.on_exit.func = func;
+ efp->funcs.on_exit.arg = arg;
+ }
+ UNLOCK;
+ return 0;
}
#endif
#ifdef L___exit_handler
-struct exit_function __exit_function_table[__MAX_EXIT];
int __exit_count = 0; /* Number of registered exit functions */
+#ifdef __UCLIBC_DYNAMIC_ATEXIT__
+struct exit_function *__exit_function_table = NULL;
+int __exit_slots = 0; /* Size of __exit_function_table */
+#else
+struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT];
+#endif
+
/*
* Handle the work of executing the registered exit functions
@@ -162,6 +197,11 @@ void __exit_handler(int status)
break;
}
}
+#ifdef __UCLIBC_DYNAMIC_ATEXIT__
+ /* Free up memory used by the __exit_function_table structure */
+ if (__exit_function_table)
+ free(__exit_function_table);
+#endif
}
#endif