/* * Call all handlers registered with __cxa_atexit for the shared * object owning 'dso'. Note: if 'dso' is NULL, then all remaining * handlers are called. */ void __cxa_finalize(void *dso) { struct dl_phdr_info phdr_info; struct atexit *p; struct atexit_fn fn; int n, has_phdr; if (dso != NULL) { has_phdr = _rtld_addr_phdr(dso, &phdr_info); } else { has_phdr = 0; global_exit = 1; } _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 */ fn = p->fns[n]; if (dso != NULL && dso != fn.fn_dso) { /* wrong DSO ? */ if (!has_phdr || global_exit || !__elf_phdr_match_addr(&phdr_info, fn.fn_ptr.cxa_func)) continue; } /* Mark entry to indicate that this particular handler has already been called. */ p->fns[n].fn_type = ATEXIT_FN_EMPTY; _MUTEX_UNLOCK(&atexit_mutex); /* Call the function of correct type. */ if (fn.fn_type == ATEXIT_FN_CXA) fn.fn_ptr.cxa_func(fn.fn_arg); else if (fn.fn_type == ATEXIT_FN_STD) fn.fn_ptr.std_func(); _MUTEX_LOCK(&atexit_mutex); } } _MUTEX_UNLOCK(&atexit_mutex); if (dso == NULL) _MUTEX_DESTROY(&atexit_mutex); if (has_phdr && !global_exit && &__pthread_cxa_finalize != NULL) __pthread_cxa_finalize(&phdr_info); }
void _thr_tsd_unload(struct dl_phdr_info *phdr_info) { struct pthread *curthread = _get_curthread(); void (*destructor)(void *); int key; THR_LOCK_ACQUIRE(curthread, &_keytable_lock); for (key = 0; key < PTHREAD_KEYS_MAX; key++) { if (_thread_keytable[key].allocated) { destructor = _thread_keytable[key].destructor; if (destructor != NULL) { if (__elf_phdr_match_addr(phdr_info, destructor)) _thread_keytable[key].destructor = NULL; } } } THR_LOCK_RELEASE(curthread, &_keytable_lock); }