[PATCH v3] dlfcn: Fix dlclose crash in atexit handler after thread_local destructor (BZ 33598)
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Tue May 5 20:45:25 GMT 2026
On 05/05/26 16:36, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> @@ -46,6 +47,9 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
>> /* The exit should never return, so there is no need to unlock it. */
>> __libc_lock_lock_recursive (__exit_lock);
>>
>> + /* Disable unmap objects through dlclose by TLS destructor (BZ 33598). */
>> + GL(dl_at_exit) = true;
>> +
>> /* First, call the TLS destructors. */
>> if (run_dtors)
>> call_function_static_weak (__call_tls_dtors);
>> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
>> index 15c46598539..236419c593c 100644
>> --- a/sysdeps/generic/ldsodefs.h
>> +++ b/sysdeps/generic/ldsodefs.h
>> @@ -441,6 +441,9 @@ struct rtld_global
>> /* Generation counter for the dtv. */
>> EXTERN size_t _dl_tls_generation;
>>
>> + /* Disable unmap objects during __run_exit_handlers. */
>> + EXTERN bool _dl_at_exit;
>> +
>> /* Scopes to free after next THREAD_GSCOPE_WAIT (). */
>> EXTERN struct dl_scope_free_list
>> {
>
> Would it be simpler to do what the comment says? Just guard the
> munmap call that is part of dlclose? This could even be considered an
> optimization.
It should work, the main difference is with this approach (assume_in_use = false),
_dl_close_worker during exit marks every object IDX_STILL_USED and returns
immediately, so fo finalizers run. The _dl_fini handles every library in its
own sorted pass later.
With the DL_UNMAP approach, _dl_close_worker runs normally and unloadable libraries
get their finalizers called by _dl_call_fini inside _dl_close_worker.
I think it makes sense to use your suggestion. I will send a new version.
More information about the Libc-alpha
mailing list