os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32): Define.
authorYaakov Selkowitz <yselkowi@redhat.com>
Tue, 19 Aug 2014 15:25:12 +0000 (15:25 +0000)
committerKai Tietz <ktietz@gcc.gnu.org>
Tue, 19 Aug 2014 15:25:12 +0000 (17:25 +0200)
2014-08-19  Yaakov Selkowitz  <yselkowi@redhat.com>
Kai Tietz  <ktietz@redhat.com>

* config/os/mingw32-w64/os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32):
Define.
* config/os/newlib/os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32):
Ditto.
* libsupc++/atexit_thread.cc [_GLIBCXX_THREAD_ATEXIT_WIN32]:
#include <windows.h>.
(struct elt): Add dll member.
(run): Decrement dll refcount.
(__cxxabiv1::__cxa_thread_atexit): Increment dll refcount.

Co-Authored-By: Kai Tietz <ktietz@redhat.com>
From-SVN: r214163

libstdc++-v3/ChangeLog
libstdc++-v3/config/os/mingw32-w64/os_defines.h
libstdc++-v3/config/os/newlib/os_defines.h
libstdc++-v3/libsupc++/atexit_thread.cc

index 7154111..c764927 100644 (file)
@@ -1,3 +1,16 @@
+2014-08-19  Yaakov Selkowitz  <yselkowi@redhat.com>
+       Kai Tietz  <ktietz@redhat.com>
+
+       * config/os/mingw32-w64/os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32):
+       Define.
+       * config/os/newlib/os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32):
+       Ditto.
+       * libsupc++/atexit_thread.cc [_GLIBCXX_THREAD_ATEXIT_WIN32]:
+       #include <windows.h>.
+       (struct elt): Add dll member.
+       (run): Decrement dll refcount.
+       (__cxxabiv1::__cxa_thread_atexit): Increment dll refcount.
+
 2014-08-15  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/62154
index c736f6c..5e7aec8 100644 (file)
@@ -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 92748da..2e01d3b 100644 (file)
 
 // 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 dff08e9..d7d84d2 100644 (file)
 #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 @@ namespace {
     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 @@ namespace {
       {
        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 @@ __cxxabiv1::__cxa_thread_atexit (void (*dtor)(void *), void *obj, void */*dso_ha
   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);