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
This commit is contained in:
kib 2013-12-06 21:26:57 +00:00
parent 49a4972ff7
commit 44b7f6b41b

View File

@ -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);
}