Imported Upstream version 2.73.3
[platform/upstream/glib.git] / glib / gthread-win32.c
index 66558df..8010520 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright 1998-2001 Sebastian Wilhelmi; University of Karlsruhe
  * Copyright 2001 Hans Breuer
  *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -307,19 +309,29 @@ static CRITICAL_SECTION g_private_lock;
 static DWORD
 g_private_get_impl (GPrivate *key)
 {
-  DWORD impl = (DWORD) key->p;
+  DWORD impl = (DWORD) GPOINTER_TO_UINT(key->p);
 
   if G_UNLIKELY (impl == 0)
     {
       EnterCriticalSection (&g_private_lock);
-      impl = (DWORD) key->p;
+      impl = (UINT_PTR) key->p;
       if (impl == 0)
         {
           GPrivateDestructor *destructor;
 
           impl = TlsAlloc ();
 
-          if (impl == TLS_OUT_OF_INDEXES)
+          if G_UNLIKELY (impl == 0)
+            {
+              /* Ignore TLS index 0 temporarily (as 0 is the indicator that we
+               * haven't allocated TLS yet) and alloc again;
+               * See https://gitlab.gnome.org/GNOME/glib/-/issues/2058 */
+              DWORD impl2 = TlsAlloc ();
+              TlsFree (impl);
+              impl = impl2;
+            }
+
+          if (impl == TLS_OUT_OF_INDEXES || impl == 0)
             g_thread_abort (0, "TlsAlloc");
 
           if (key->notify != NULL)
@@ -412,6 +424,28 @@ g_system_thread_free (GRealThread *thread)
 void
 g_system_thread_exit (void)
 {
+  /* In static compilation, DllMain doesn't exist and so DLL_THREAD_DETACH
+   * case is never called and thread destroy notifications are not triggered.
+   * To ensure that notifications are correctly triggered in static
+   * compilation mode, we call directly the "detach" function here right
+   * before terminating the thread.
+   * As all win32 threads initialized through the glib API are run through
+   * the same proxy function g_thread_win32_proxy() which calls systematically
+   * g_system_thread_exit() when finishing, we obtain the same behavior as
+   * with dynamic compilation.
+   *
+   * WARNING: unfortunately this mechanism cannot work with threads created
+   * directly from the Windows API using CreateThread() or _beginthread/ex().
+   * It only works with threads created by using the glib API with
+   * g_system_thread_new(). If users need absolutely to use a thread NOT
+   * created with glib API under Windows and in static compilation mode, they
+   * should not use glib functions within their thread or they may encounter
+   * memory leaks when the thread finishes.
+   */
+#ifdef GLIB_STATIC_COMPILATION
+  g_thread_win32_thread_detach ();
+#endif
+
   _endthreadex (0);
 }
 
@@ -504,7 +538,7 @@ g_system_thread_new (GThreadFunc proxy,
       goto error;
     }
 
-  if (ResumeThread (thread->handle) == -1)
+  if (ResumeThread (thread->handle) == (DWORD) -1)
     {
       message = "Error resuming new thread";
       goto error;
@@ -593,21 +627,21 @@ SetThreadName (DWORD  dwThreadID,
    if ((!IsDebuggerPresent ()) && (SetThreadName_VEH_handle == NULL))
      return;
 
-   RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (DWORD *) &info);
+   RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (const ULONG_PTR *) &info);
 #endif
 }
 
 typedef HRESULT (WINAPI *pSetThreadDescription) (HANDLE hThread,
                                                  PCWSTR lpThreadDescription);
 static pSetThreadDescription SetThreadDescriptionFunc = NULL;
-HMODULE kernel32_module = NULL;
+static HMODULE kernel32_module = NULL;
 
 static gboolean
 g_thread_win32_load_library (void)
 {
   /* FIXME: Add support for UWP app */
 #if !defined(G_WINAPI_ONLY_APP)
-  static volatile gsize _init_once = 0;
+  static gsize _init_once = 0;
   if (g_once_init_enter (&_init_once))
     {
       kernel32_module = LoadLibraryW (L"kernel32.dll");