[glib: 1/2] Fix g_module_symbol() under Windows sometimes not succeeding




commit 6a903ff6d79d967675fb6355360ccb60e7d4c826
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Tue Sep 29 18:41:00 2020 +0200

    Fix g_module_symbol() under Windows sometimes not succeeding
    
    g_module_symbol() internally calls CreateToolhelp32Snapshot() which
    in some circumstances returns ERROR_BAD_LENGTH and according to the docs
    should lead to CreateToolhelp32Snapshot() being retried by the caller.
    
    This retry logic was missing and for example led to g_module_symbol()
    not succeeding if another thread happened to call the wrong function
    at the wrong time.
    
    This got noticed in the g-i build of gtk4 where g-i would call g_module_symbol()
    on all gtk4 _get_type symbols and while inspecting the properties gtk4 would
    spawn a thread calling SHGetSpecialFolderLocation() somewhere down the line.
    During the call to SHGetSpecialFolderLocation() CreateToolhelp32Snapshot() would
    return with ERROR_BAD_LENGTH for a short period of time and make g_module_symbol()
    fail, which lead to "Invalid GType function" errors in g-i.
    
    Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3213

 gmodule/gmodule-win32.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
---
diff --git a/gmodule/gmodule-win32.c b/gmodule/gmodule-win32.c
index fef4d893d..2aea8bae9 100644
--- a/gmodule/gmodule-win32.c
+++ b/gmodule/gmodule-win32.c
@@ -131,7 +131,20 @@ find_in_any_module_using_toolhelp (const gchar *symbol_name)
   /* Under UWP, Module32Next and Module32First are not available since we're
    * not allowed to search in the address space of arbitrary loaded DLLs */
 #if !defined(G_WINAPI_ONLY_APP)
-  if ((snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0)) == (HANDLE) -1)
+  /* https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot#remarks
+   * If the function fails with ERROR_BAD_LENGTH, retry the function until it succeeds. */
+  while (TRUE)
+    {
+      snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0);
+      if (snapshot == INVALID_HANDLE_VALUE && GetLastError () == ERROR_BAD_LENGTH)
+        {
+          g_thread_yield ();
+          continue;
+        }
+      break;
+    }
+
+  if (snapshot == INVALID_HANDLE_VALUE)
     return NULL;
 
   me32.dwSize = sizeof (me32);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]