aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2013-12-06 21:26:57 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2013-12-06 21:26:57 +0000
commita7afea438206b99a9676ba3139d07e896b9dd6f2 (patch)
tree13595e4836b4ca4c2b34ca8094f3420afdd4c10e /lib
parent2727e97436b32493fbab4cb95ae32f411e6d95ba (diff)
downloadsrc-a7afea438206b99a9676ba3139d07e896b9dd6f2.tar.gz
src-a7afea438206b99a9676ba3139d07e896b9dd6f2.zip
Do not force to run atexit handlers, which text comes from a dso
owning the handle passed to __cxa_finalize() but which are registered by other dso, when the process is inside exit(3). Running them makes the destruction order wrong, and there is hope that such destructors would not call dlclose(3), since it is pointless at this stage of the process existence. The change effectively disables the r211706 after the exit(3) is called. Reported and tested by: Michael Gmelin <freebsd@grem.de> Analyzed by: dim Sponsored by: The FreeBSD Foundation MFC after: 1 week
Notes
Notes: svn path=/head/; revision=259042
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/atexit.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
index 18c31c3b1ffb..01d09fede286 100644
--- a/lib/libc/stdlib/atexit.c
+++ b/lib/libc/stdlib/atexit.c
@@ -151,6 +151,8 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
#pragma weak __pthread_cxa_finalize
void __pthread_cxa_finalize(const struct dl_phdr_info *);
+static int global_exit;
+
/*
* Call all handlers registered with __cxa_atexit for the shared
* object owning 'dso'. Note: if 'dso' is NULL, then all remaining
@@ -164,10 +166,12 @@ __cxa_finalize(void *dso)
struct atexit_fn fn;
int n, has_phdr;
- if (dso != NULL)
+ if (dso != NULL) {
has_phdr = _rtld_addr_phdr(dso, &phdr_info);
- else
+ } else {
has_phdr = 0;
+ global_exit = 1;
+ }
_MUTEX_LOCK(&atexit_mutex);
for (p = __atexit; p; p = p->next) {
@@ -177,8 +181,9 @@ __cxa_finalize(void *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))
+ if (!has_phdr || global_exit ||
+ !__elf_phdr_match_addr(&phdr_info,
+ fn.fn_ptr.cxa_func))
continue;
}
/*
@@ -200,6 +205,6 @@ __cxa_finalize(void *dso)
if (dso == NULL)
_MUTEX_DESTROY(&atexit_mutex);
- if (has_phdr && &__pthread_cxa_finalize != NULL)
+ if (has_phdr && !global_exit && &__pthread_cxa_finalize != NULL)
__pthread_cxa_finalize(&phdr_info);
}