gslice: Inline win32 implementation of g_getenv() to avoid deadlock

The win32 implementation of `g_getenv()` uses GSlice (from within
GQuark), which results in a deadlock when examining the `G_SLICE`
environment variable.

Fix that by inlining a basic implementation of `g_getenv()` at that call
site.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>

Fixes: #2225
This commit is contained in:
Philip Withnall 2020-10-15 10:20:10 +01:00
parent e2e8339e0a
commit b538cb0c8c

View File

@ -361,10 +361,52 @@ static void
slice_config_init (SliceConfig *config)
{
const gchar *val;
gchar *val_allocated = NULL;
*config = slice_config;
/* Note that the empty string (`G_SLICE=""`) is treated differently from the
* envvar being unset. In the latter case, we also check whether running under
* valgrind. */
#ifndef G_OS_WIN32
val = g_getenv ("G_SLICE");
#else
/* The win32 implementation of g_getenv() has to do UTF-8 ↔ UTF-16 conversions
* which use the slice allocator, leading to deadlock. Use a simple in-place
* implementation here instead.
*
* Ignore references to other environment variables: only support values which
* are a combination of always-malloc and debug-blocks. */
{
wchar_t wvalue[128]; /* at least big enough for `always-malloc,debug-blocks` */
int len;
len = GetEnvironmentVariableW (L"G_SLICE", wvalue, G_N_ELEMENTS (wvalue));
if (len == 0)
{
if (GetLastError () == ERROR_ENVVAR_NOT_FOUND)
val = NULL;
else
val = "";
}
else if (len >= G_N_ELEMENTS (wvalue))
{
/* @wvalue isnt big enough. Give up. */
g_warning ("Unsupported G_SLICE value");
val = NULL;
}
else
{
/* its safe to use g_utf16_to_utf8() here as it only allocates using
* malloc() rather than GSlice */
val = val_allocated = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
}
}
#endif /* G_OS_WIN32 */
if (val != NULL)
{
gint flags;
@ -392,6 +434,8 @@ slice_config_init (SliceConfig *config)
config->always_malloc = TRUE;
#endif
}
g_free (val_allocated);
}
static void