From 477ff949e11238004ec73c5662e9490124184664 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 28 Jul 2022 17:14:19 +0200 Subject: [PATCH] gspawn-win32: Provide thread-safe wrappers for _wspawn*e functions _wspawn*e functions are not thread safe on the MSVCRT.dll and the pre-2015 MSVC runtime DLLs (msvcrXXX.dll). --- glib/gspawn-win32.c | 57 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/glib/gspawn-win32.c b/glib/gspawn-win32.c index 5ac4910f8..cae4c288c 100644 --- a/glib/gspawn-win32.c +++ b/glib/gspawn-win32.c @@ -64,6 +64,10 @@ #include #include +#ifdef _MSC_VER +#include /* for _UCRT */ +#endif + #ifndef GSPAWN_HELPER #ifdef G_SPAWN_WIN32_DEBUG static int debug = 1; @@ -117,6 +121,53 @@ enum { #define HELPER_PROCESS "gspawn-win32-helper" #endif +#ifndef _UCRT + +/* The wspawn*e functions are thread-safe only in the Universal + * CRT (UCRT). If we are linking against the MSVCRT.dll or the + * pre-2015 MSVC runtime (MSVCRXXX.dll), then we have to use a + * mutex. + */ + +static GMutex safe_wspawn_e_mutex; + +static intptr_t +safe_wspawnve (int _Mode, + const wchar_t *_Filename, + const wchar_t *const *_ArgList, + const wchar_t *const *_Env) +{ + intptr_t ret_val = -1; + + g_mutex_lock (&safe_wspawn_e_mutex); + ret_val = _wspawnve (_Mode, _Filename, _ArgList, _Env); + g_mutex_unlock (&safe_wspawn_e_mutex); + + return ret_val; +} + +static intptr_t +safe_wspawnvpe (int _Mode, + const wchar_t *_Filename, + const wchar_t *const *_ArgList, + const wchar_t *const *_Env) +{ + intptr_t ret_val = -1; + + g_mutex_lock (&safe_wspawn_e_mutex); + ret_val = _wspawnvpe (_Mode, _Filename, _ArgList, _Env); + g_mutex_unlock (&safe_wspawn_e_mutex); + + return ret_val; +} + +#else + +#define safe_wspawnve _spawnve +#define safe_wspawnvpe _wspawnvpe + +#endif /* _UCRT */ + /* This logic has a copy for wchar_t in gspawn-win32-helper.c, protect_wargv() */ static gchar * protect_argv_string (const gchar *string) @@ -489,12 +540,12 @@ do_spawn_directly (gint *exit_status, if (flags & G_SPAWN_SEARCH_PATH) if (wenvp != NULL) - rc = _wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); + rc = safe_wspawnvpe (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); else rc = _wspawnvp (mode, wargv0, (const wchar_t **) wargv); else if (wenvp != NULL) - rc = _wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); + rc = safe_wspawnve (mode, wargv0, (const wchar_t **) wargv, (const wchar_t **) wenvp); else rc = _wspawnv (mode, wargv0, (const wchar_t **) wargv); @@ -833,7 +884,7 @@ fork_exec (gint *exit_status, g_free (helper_process); if (wenvp != NULL) - rc = _wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp); + rc = safe_wspawnvpe (P_NOWAIT, whelper, (const wchar_t **) wargv, (const wchar_t **) wenvp); else rc = _wspawnvp (P_NOWAIT, whelper, (const wchar_t **) wargv);