On 28/10/2025 11:48, Takashi Yano wrote:
If dlclose() for the first DLL is called in the destructor of another
linked DLL, __cxa_finalize() should be called even in exit_state. This
is because if the second destructor is called in exit_state, the first
DLL will be unloaded by dlclose(). Therefore, if __cxa_finalize() is
not called here, the destructor of the first DLL will be called in exit()
even though the first DLL is already unloaded. This causes crash at
exit(). In the case above, __cxa_finalize() should be called before
unloading the first DLL even in exit_state.
I realize the situation is complex, but this is kind of hard to follow.
"first DLL" and "second DLL" doesn't really clarify the the relationship
between them. I guess it's something like DLL A is dlopened, which links
with DLL B? So that might be a better?
Addresses: https://cygwin.com/pipermail/cygwin/2025-October/258877.html
Fixes: c019a66c32f8 ("* dll_init.cc (dll_list::detach) ... Don't call __cxa_finalize
in exiting case.")
Reported-by: Thomas Huth <[email protected]>
Reviewed-by:
Signed-off-by: Takashi Yano <[email protected]>
---
winsup/cygwin/dll_init.cc | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 1369165c9..b6ab4ed11 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -584,7 +584,8 @@ dll_list::detach (void *retaddr)
/* Ensure our exception handler is enabled for destructors */
exception protect;
/* Call finalize function if we are not already exiting */
- if (!exit_state)
+ /* Loaded DLLs need finalize function even in the exiting state */
"We always call the finialize function for run-time loaded (dlopened)
DLLs because..."
+ if (!exit_state || d->type == DLL_LOAD)
__cxa_finalize (d->handle);
d->run_dtors ();
}