mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-23 01:18:53 +02:00
Work around an UCRT issue with _wspawn() functions taking an environment block argument
We were working around that with a call to chdir("."). Internally chdir() sets up cmd shell-related environment variables, but only if the current working directory belongs to a volume with a drive letter. For example, if the current working directory is on a UNC volume like a network share, the call to chdir() won't help. Reference: https://developercommunity.visualstudio.com/t/UCRT-Crash-in-_wspawne-functions/10262748
This commit is contained in:
committed by
Philip Withnall
parent
8b45b81150
commit
911d091866
@@ -65,8 +65,10 @@
|
|||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#ifdef HAVE_VCRUNTIME_H
|
||||||
#include <vcruntime.h> /* for _UCRT */
|
#include <vcruntime.h> /* for _UCRT */
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef GSPAWN_HELPER
|
#ifndef GSPAWN_HELPER
|
||||||
#ifdef G_SPAWN_WIN32_DEBUG
|
#ifdef G_SPAWN_WIN32_DEBUG
|
||||||
@@ -163,8 +165,85 @@ safe_wspawnvpe (int _Mode,
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define safe_wspawnve _wspawnve
|
/**< private >
|
||||||
#define safe_wspawnvpe _wspawnvpe
|
* ensure_cmd_environment:
|
||||||
|
*
|
||||||
|
* Workaround for an issue in the universal C Runtime library (UCRT). This adds
|
||||||
|
* a custom environment variable to this process's environment block that looks
|
||||||
|
* like the cmd.exe's shell-related environment variables, i.e the name starts
|
||||||
|
* with an equal sign character: '='. This is needed because the UCRT may crash
|
||||||
|
* if those environment variables are missing from the calling process's block.
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
*
|
||||||
|
* https://developercommunity.visualstudio.com/t/UCRT-Crash-in-_wspawne-functions/10262748
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ensure_cmd_environment (void)
|
||||||
|
{
|
||||||
|
static gsize initialization_value = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&initialization_value))
|
||||||
|
{
|
||||||
|
wchar_t *block = GetEnvironmentStringsW ();
|
||||||
|
gboolean have_cmd_environment = FALSE;
|
||||||
|
|
||||||
|
if (block)
|
||||||
|
{
|
||||||
|
const wchar_t *p = block;
|
||||||
|
|
||||||
|
while (*p != L'\0')
|
||||||
|
{
|
||||||
|
if (*p == L'=')
|
||||||
|
{
|
||||||
|
have_cmd_environment = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += wcslen (p) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FreeEnvironmentStringsW (block))
|
||||||
|
g_warning ("%s failed with error code %u",
|
||||||
|
"FreeEnvironmentStrings",
|
||||||
|
(guint) GetLastError ());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_cmd_environment)
|
||||||
|
{
|
||||||
|
if (!SetEnvironmentVariableW (L"=GLIB", L"GLIB"))
|
||||||
|
{
|
||||||
|
g_critical ("%s failed with error code %u",
|
||||||
|
"SetEnvironmentVariable",
|
||||||
|
(guint) GetLastError ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_once_init_leave (&initialization_value, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static intptr_t
|
||||||
|
safe_wspawnve (int _mode,
|
||||||
|
const wchar_t * _filename,
|
||||||
|
const wchar_t *const *_args,
|
||||||
|
const wchar_t *const *_env)
|
||||||
|
{
|
||||||
|
ensure_cmd_environment ();
|
||||||
|
|
||||||
|
return _wspawnve (_mode, _filename, _args, _env);;
|
||||||
|
}
|
||||||
|
|
||||||
|
static intptr_t
|
||||||
|
safe_wspawnvpe (int _mode,
|
||||||
|
const wchar_t * _filename,
|
||||||
|
const wchar_t *const *_args,
|
||||||
|
const wchar_t *const *_env)
|
||||||
|
{
|
||||||
|
ensure_cmd_environment ();
|
||||||
|
|
||||||
|
return _wspawnvpe (_mode, _filename, _args, _env);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _UCRT */
|
#endif /* _UCRT */
|
||||||
|
|
||||||
@@ -686,13 +765,6 @@ fork_exec (gint *exit_status,
|
|||||||
|
|
||||||
argc = protect_argv (argv, &protected_argv);
|
argc = protect_argv (argv, &protected_argv);
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: Workaround broken spawnvpe functions that SEGV when "=X:="
|
|
||||||
* environment variables are missing. Calling chdir() will set the magic
|
|
||||||
* environment variable again.
|
|
||||||
*/
|
|
||||||
_chdir (".");
|
|
||||||
|
|
||||||
if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
|
if (stdin_fd == -1 && stdout_fd == -1 && stderr_fd == -1 &&
|
||||||
(flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
|
(flags & G_SPAWN_CHILD_INHERITS_STDIN) &&
|
||||||
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
|
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL) &&
|
||||||
|
Reference in New Issue
Block a user