+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
#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
// 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
#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
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.
{
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);
}
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);