[glib/glib-2-66: 1/2] gslice: Inline win32 implementation of g_getenv() to avoid deadlock




commit 7f450baab77519a58131bf9cd8f6183c489b9faa
Author: Philip Withnall <pwithnall endlessos org>
Date:   Thu Oct 15 10:20:10 2020 +0100

    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

 glib/gslice.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
---
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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]