diff mbox

_cxa_thread_atexit fixes for Cygwin/MinGW-w64

Message ID 53ED2265.90201@redhat.com
State New
Headers show

Commit Message

Yaakov Selkowitz Aug. 14, 2014, 8:56 p.m. UTC
The attached patch implements premature DLL unloading prevention in 
__cxa_thread_atexit for Cygwin and MinGW-w64 targets.  The mingw.org 
target is welcome to do the same in their os_defines.h, but this code 
does require Windows XP/2003, and they have historically catered to 
older platforms.

MinGW cannot practically implement __cxa_thread_atexit_impl because it 
has no control over the contents of its libc (msvcrt), and implementing 
this in the (static) mingw32 support library would be of little benefit 
because it would still end up statically linked into libstdc++.  Also, 
the GPL-with-exceptions libstdc++ implementation cannot be copied as a 
basis of our own __cxa_thread_atexit_impl due to licensing conflicts 
with both Cygwin (copyright assignment) and MinGW (public domain).

The testsuite shows no regressions with this patch.

Comments

Kai Tietz Aug. 19, 2014, 3:26 p.m. UTC | #1
Applied at revision 214163.

Thanks,
Kai
diff mbox

Patch

Index: libstdc++-v3/config/os/mingw32-w64/os_defines.h
===================================================================
--- libstdc++-v3/config/os/mingw32-w64/os_defines.h	(revision 213759)
+++ libstdc++-v3/config/os/mingw32-w64/os_defines.h	(working copy)
@@ -78,4 +78,9 @@ 
 #define _GLIBCXX_LLP64 1
 #endif
 
+// Enable use of GetModuleHandleEx (requires Windows XP/2003) in
+// __cxa_thread_atexit to prevent modules from being unloaded before
+// their dtors are called
+#define _GLIBCXX_THREAD_ATEXIT_WIN32 1
+
 #endif
Index: libstdc++-v3/config/os/newlib/os_defines.h
===================================================================
--- libstdc++-v3/config/os/newlib/os_defines.h	(revision 213759)
+++ libstdc++-v3/config/os/newlib/os_defines.h	(working copy)
@@ -47,6 +47,12 @@ 
 
 // See libstdc++/20806.
 #define _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM 1
+
+// Enable use of GetModuleHandleEx (requires Windows XP/2003) in
+// __cxa_thread_atexit to prevent modules from being unloaded before
+// their dtors are called
+#define _GLIBCXX_THREAD_ATEXIT_WIN32 1
+
 #endif
 
 #endif
Index: libstdc++-v3/libsupc++/atexit_thread.cc
===================================================================
--- libstdc++-v3/libsupc++/atexit_thread.cc	(revision 213759)
+++ libstdc++-v3/libsupc++/atexit_thread.cc	(working copy)
@@ -25,6 +25,10 @@ 
 #include <cstdlib>
 #include <new>
 #include "bits/gthr.h"
+#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
 
 #if _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
 
@@ -47,6 +51,9 @@ 
     void (*destructor)(void *);
     void *object;
     elt *next;
+#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+    HMODULE dll;
+#endif
   };
 
   // Keep a per-thread list of cleanups in gthread_key storage.
@@ -62,6 +69,11 @@ 
       {
 	elt *old_e = e;
 	e->destructor (e->object);
+#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+	/* Decrement DLL count */
+	if (e->dll)
+	  FreeLibrary (e->dll);
+#endif
 	e = e->next;
 	delete (old_e);
       }
@@ -133,6 +145,14 @@ 
   new_elt->destructor = dtor;
   new_elt->object = obj;
   new_elt->next = first;
+#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
+  /* Store the DLL address for a later call to FreeLibrary in new_elt and
+     increment DLL load count.  This blocks the unloading of the DLL
+     before the thread-local dtors have been called.  This does NOT help
+     if FreeLibrary/dlclose is called in excess. */
+  GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+		      (LPCWSTR) dtor, &new_elt->dll);
+#endif
 
   if (__gthread_active_p ())
     __gthread_setspecific (key, new_elt);