From 1ed3ba0549f544bd9dd5195d7045b20dec0354a3 Mon Sep 17 00:00:00 2001 From: Yaakov Selkowitz Date: Tue, 19 Aug 2014 15:25:12 +0000 Subject: [PATCH] os_defines.h (_GLIBCXX_THREAD_ATEXIT_WIN32): Define. 2014-08-19 Yaakov Selkowitz Kai Tietz * 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 . (struct elt): Add dll member. (run): Decrement dll refcount. (__cxxabiv1::__cxa_thread_atexit): Increment dll refcount. Co-Authored-By: Kai Tietz From-SVN: r214163 --- libstdc++-v3/ChangeLog | 13 ++++++++++++ .../config/os/mingw32-w64/os_defines.h | 5 +++++ libstdc++-v3/config/os/newlib/os_defines.h | 6 ++++++ libstdc++-v3/libsupc++/atexit_thread.cc | 20 +++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 71541111c75..c7649272255 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2014-08-19 Yaakov Selkowitz + Kai Tietz + + * 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 . + (struct elt): Add dll member. + (run): Decrement dll refcount. + (__cxxabiv1::__cxa_thread_atexit): Increment dll refcount. + 2014-08-15 Jonathan Wakely PR libstdc++/62154 diff --git a/libstdc++-v3/config/os/mingw32-w64/os_defines.h b/libstdc++-v3/config/os/mingw32-w64/os_defines.h index c736f6c04bf..5e7aec8e458 100644 --- a/libstdc++-v3/config/os/mingw32-w64/os_defines.h +++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h @@ -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 diff --git a/libstdc++-v3/config/os/newlib/os_defines.h b/libstdc++-v3/config/os/newlib/os_defines.h index 92748dad635..2e01d3bdf7d 100644 --- a/libstdc++-v3/config/os/newlib/os_defines.h +++ b/libstdc++-v3/config/os/newlib/os_defines.h @@ -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 diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc index dff08e92477..d7d84d2c626 100644 --- a/libstdc++-v3/libsupc++/atexit_thread.cc +++ b/libstdc++-v3/libsupc++/atexit_thread.cc @@ -25,6 +25,10 @@ #include #include #include "bits/gthr.h" +#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#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); -- 2.30.2