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
This commit is contained in:
Christoph Reiter 2020-09-29 18:41:00 +02:00
parent 010569b373
commit 6a903ff6d7

View File

@ -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);