mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-10-20 04:12:52 +02:00
win32: stop leaking GPrivate data
Instead of running the GPrivate destructors from our thread proxy code, run it from the DllMain handler for the DLL_THREAD_DETACH case. This should ensure that thread-local data is free at the exit of all threads -- not just the ones we created for ourselves. https://bugzilla.gnome.org/show_bug.cgi?id=660745
This commit is contained in:
@@ -225,6 +225,10 @@ DllMain (HINSTANCE hinstDLL,
|
|||||||
glib_init ();
|
glib_init ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DLL_THREAD_DETACH:
|
||||||
|
g_thread_win32_thread_detach ();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
;
|
;
|
||||||
|
@@ -31,6 +31,7 @@ GLIB_VAR gboolean g_mem_gc_friendly;
|
|||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
G_GNUC_INTERNAL void g_thread_win32_thread_detach (void);
|
||||||
G_GNUC_INTERNAL void g_thread_win32_init (void);
|
G_GNUC_INTERNAL void g_thread_win32_init (void);
|
||||||
G_GNUC_INTERNAL extern HMODULE glib_dll;
|
G_GNUC_INTERNAL extern HMODULE glib_dll;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -489,51 +489,6 @@ g_system_thread_self (gpointer thread)
|
|||||||
void
|
void
|
||||||
g_system_thread_exit (void)
|
g_system_thread_exit (void)
|
||||||
{
|
{
|
||||||
GThreadData *self = TlsGetValue (g_thread_self_tls);
|
|
||||||
gboolean dtors_called;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
GPrivateDestructor *dtor;
|
|
||||||
|
|
||||||
/* We go by the POSIX book on this one.
|
|
||||||
*
|
|
||||||
* If we call a destructor then there is a chance that some new
|
|
||||||
* TLS variables got set by code called in that destructor.
|
|
||||||
*
|
|
||||||
* Loop until nothing is left.
|
|
||||||
*/
|
|
||||||
dtors_called = FALSE;
|
|
||||||
|
|
||||||
for (dtor = g_private_destructors; dtor; dtor = dtor->next)
|
|
||||||
{
|
|
||||||
gpointer value;
|
|
||||||
|
|
||||||
value = TlsGetValue (dtor->index);
|
|
||||||
if (value != NULL && dtor->notify != NULL)
|
|
||||||
{
|
|
||||||
/* POSIX says to clear this before the call */
|
|
||||||
TlsSetValue (dtor->index, NULL);
|
|
||||||
dtor->notify (value);
|
|
||||||
dtors_called = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (dtors_called);
|
|
||||||
|
|
||||||
if (self)
|
|
||||||
{
|
|
||||||
if (!self->joinable)
|
|
||||||
{
|
|
||||||
win32_check_for_error (CloseHandle (self->thread));
|
|
||||||
g_free (self);
|
|
||||||
}
|
|
||||||
win32_check_for_error (TlsSetValue (g_thread_self_tls, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_thread_impl_vtable.CallThisOnThreadExit)
|
|
||||||
g_thread_impl_vtable.CallThisOnThreadExit ();
|
|
||||||
|
|
||||||
_endthreadex (0);
|
_endthreadex (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1085,5 +1040,53 @@ g_thread_win32_init (void)
|
|||||||
InitializeCriticalSection (&g_private_lock);
|
InitializeCriticalSection (&g_private_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim:set foldmethod=marker: */
|
G_GNUC_INTERNAL void
|
||||||
|
g_thread_win32_thread_detach (void)
|
||||||
|
{
|
||||||
|
GThreadData *self = TlsGetValue (g_thread_self_tls);
|
||||||
|
gboolean dtors_called;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
GPrivateDestructor *dtor;
|
||||||
|
|
||||||
|
/* We go by the POSIX book on this one.
|
||||||
|
*
|
||||||
|
* If we call a destructor then there is a chance that some new
|
||||||
|
* TLS variables got set by code called in that destructor.
|
||||||
|
*
|
||||||
|
* Loop until nothing is left.
|
||||||
|
*/
|
||||||
|
dtors_called = FALSE;
|
||||||
|
|
||||||
|
for (dtor = g_private_destructors; dtor; dtor = dtor->next)
|
||||||
|
{
|
||||||
|
gpointer value;
|
||||||
|
|
||||||
|
value = TlsGetValue (dtor->index);
|
||||||
|
if (value != NULL && dtor->notify != NULL)
|
||||||
|
{
|
||||||
|
/* POSIX says to clear this before the call */
|
||||||
|
TlsSetValue (dtor->index, NULL);
|
||||||
|
dtor->notify (value);
|
||||||
|
dtors_called = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (dtors_called);
|
||||||
|
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
if (!self->joinable)
|
||||||
|
{
|
||||||
|
win32_check_for_error (CloseHandle (self->thread));
|
||||||
|
g_free (self);
|
||||||
|
}
|
||||||
|
win32_check_for_error (TlsSetValue (g_thread_self_tls, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_thread_impl_vtable.CallThisOnThreadExit)
|
||||||
|
g_thread_impl_vtable.CallThisOnThreadExit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:set foldmethod=marker: */
|
||||||
|
Reference in New Issue
Block a user