If dlclose() for DLL A is called in the destructor of DLL B which linked with the main program, __cxa_finalize() should be called even in exit_state. This is because if the destructor of DLL B is called in exit_state, DLL A will be unloaded by dlclose(). Thereofre, if __cxa_finalize()is not called here, the destructor of DLL A will be called in exit() even though DLL A is already unloaded. This causes crash at exit(). In the case above, __cxa_finalize() should be called before unloading DLL A even in exit_state.
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: Mark Geisert <[email protected]>, Jon Turney <[email protected]> Signed-off-by: Takashi Yano <[email protected]> --- winsup/cygwin/dll_init.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 1369165c9..5ef0fa875 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -584,7 +584,10 @@ 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) + /* We always call the finalize function for a dlopen()'ed DLL + because its destructor may crash if invoked during exit() + after dlclose(). */ + if (!exit_state || d->type == DLL_LOAD) __cxa_finalize (d->handle); d->run_dtors (); } -- 2.51.0
