summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2020-10-16 11:22:02 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2020-10-16 11:22:02 +0000
commite591d2e4ccc53bce730a24ddd92550ca6aa8599e (patch)
treeaa37de978f7e5357326f6f39e53bcfe80ffafb97
parented00ee3c9e74375e9a3d59f3d61359537268fdf3 (diff)
parentb538cb0c8c829ba76d4a04be0c198e5d3b7c311c (diff)
downloadglib-e591d2e4ccc53bce730a24ddd92550ca6aa8599e.tar.gz
Merge branch '2225-slice-getenv-win32' into 'master'
gslice: Inline win32 implementation of g_getenv() to avoid deadlock Closes #2225 See merge request GNOME/glib!1698
-rw-r--r--glib/gslice.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/glib/gslice.c b/glib/gslice.c
index e6f278539..589619080 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -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 isn’t big enough. Give up. */
+ g_warning ("Unsupported G_SLICE value");
+ val = NULL;
+ }
+ else
+ {
+ /* it’s 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