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

Reply via email to