summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdlib/atexit.c
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2011-05-29 02:53:52 +0000
committerhrs <hrs@FreeBSD.org>2011-05-29 02:53:52 +0000
commit8fe640108653f13042f1b15213769e338aa524f6 (patch)
tree91f5675a7c792e61d68635707501027daa3f566f /lib/libc/stdlib/atexit.c
parent97f64b711efa9ff0011bef5d46cf9645638a38f9 (diff)
parentf3726238c8e8206eb1df4cfaf3f00947ceba3cce (diff)
downloadFreeBSD-src-8fe640108653f13042f1b15213769e338aa524f6.zip
FreeBSD-src-8fe640108653f13042f1b15213769e338aa524f6.tar.gz
Merge from head@222434.
Diffstat (limited to 'lib/libc/stdlib/atexit.c')
-rw-r--r--lib/libc/stdlib/atexit.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
index efd1264..511172a 100644
--- a/lib/libc/stdlib/atexit.c
+++ b/lib/libc/stdlib/atexit.c
@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94";
__FBSDID("$FreeBSD$");
#include "namespace.h"
+#include <link.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
@@ -54,6 +55,7 @@ static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
+#define _MUTEX_DESTROY(x) if (__isthreaded) _pthread_mutex_destroy(x)
struct atexit {
struct atexit *next; /* next in list */
@@ -119,7 +121,7 @@ atexit(void (*func)(void))
int error;
fn.fn_type = ATEXIT_FN_STD;
- fn.fn_ptr.std_func = func;;
+ fn.fn_ptr.std_func = func;
fn.fn_arg = NULL;
fn.fn_dso = NULL;
@@ -138,7 +140,7 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
int error;
fn.fn_type = ATEXIT_FN_CXA;
- fn.fn_ptr.cxa_func = func;;
+ fn.fn_ptr.cxa_func = func;
fn.fn_arg = arg;
fn.fn_dso = dso;
@@ -146,6 +148,9 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
return (error);
}
+#pragma weak __pthread_cxa_finalize
+void __pthread_cxa_finalize(const struct dl_phdr_info *);
+
/*
* Call all handlers registered with __cxa_atexit for the shared
* object owning 'dso'. Note: if 'dso' is NULL, then all remaining
@@ -154,18 +159,28 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
void
__cxa_finalize(void *dso)
{
+ struct dl_phdr_info phdr_info;
struct atexit *p;
struct atexit_fn fn;
- int n;
+ int n, has_phdr;
+
+ if (dso != NULL)
+ has_phdr = _rtld_addr_phdr(dso, &phdr_info);
+ else
+ has_phdr = 0;
_MUTEX_LOCK(&atexit_mutex);
for (p = __atexit; p; p = p->next) {
for (n = p->ind; --n >= 0;) {
if (p->fns[n].fn_type == ATEXIT_FN_EMPTY)
continue; /* already been called */
- if (dso != NULL && dso != p->fns[n].fn_dso)
- continue; /* wrong DSO */
fn = p->fns[n];
+ if (dso != NULL && dso != fn.fn_dso) {
+ /* wrong DSO ? */
+ if (!has_phdr || !__elf_phdr_match_addr(
+ &phdr_info, fn.fn_ptr.cxa_func))
+ continue;
+ }
/*
Mark entry to indicate that this particular handler
has already been called.
@@ -182,4 +197,9 @@ __cxa_finalize(void *dso)
}
}
_MUTEX_UNLOCK(&atexit_mutex);
+ if (dso == NULL)
+ _MUTEX_DESTROY(&atexit_mutex);
+
+ if (has_phdr && &__pthread_cxa_finalize != NULL)
+ __pthread_cxa_finalize(&phdr_info);
}
OpenPOWER on IntegriCloud