Bug 833117 - Replace g_slice_set_config() with G_SLICE environment variable. r=nfroyd,r=karlt
☠☠ backed out by c0f955560a47 ☠ ☠
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 26 Jun 2015 10:59:52 -0700
changeset 269891 f70b74488807ff3df00e9ba2b937aa5c3222acd7
parent 269855 74795c76fadc79cdd27d5bb0c08569908fec1a51
child 269892 76df0d12c09ae0a19593b4f50f298d2678208ad3
push idunknown
push userunknown
push dateunknown
reviewersnfroyd, karlt
bugs833117
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 833117 - Replace g_slice_set_config() with G_SLICE environment variable. r=nfroyd,r=karlt Using g_slice_set_config() fails with newer glib because the slice allocator now has a static constructor that runs when glib is loaded, consequently emitting a noisy error message which confuses people into believing it's the root of their problems. The only way left to force the slice allocator to use "system" malloc (in practice, jemalloc) is to set the G_SLICE environment variable to always-malloc, and that needs to happen before glib is loaded. Fortunately, the firefox and plugin-container executables don't depend on glib. Unfortunately, webapprt does, so the problem remains for web apps running through it. xpcshell and other executables that depend on libxul directly (as opposed to loading it dynamically) are not covered either.
toolkit/xre/nsAppRunner.cpp
xpcom/glue/standalone/moz.build
xpcom/glue/standalone/nsXPCOMGlue.cpp
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4320,22 +4320,16 @@ XREMain::XRE_main(int argc, char* argv[]
     SetAllocatedString(mAppData->remotingName, mAppData->name);
   }
   // used throughout this file
   gAppData = mAppData;
 
   mozilla::IOInterposerInit ioInterposerGuard;
 
 #if defined(MOZ_WIDGET_GTK)
-#if defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__)
-  // Disable the slice allocator, since jemalloc already uses similar layout
-  // algorithms, and using a sub-allocator tends to increase fragmentation.
-  // This must be done before g_thread_init() is called.
-  g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, 1);
-#endif
   g_thread_init(nullptr);
 #endif
 
   // init
   bool exit = false;
   int result = XRE_mainInit(&exit);
   if (result != 0 || exit)
     return result;
--- a/xpcom/glue/standalone/moz.build
+++ b/xpcom/glue/standalone/moz.build
@@ -49,8 +49,11 @@ FAIL_ON_WARNINGS = True
 USE_LIBS += [
     'fallible',
 ]
 
 # Force to build a static library only
 NO_EXPAND_LIBS = True
 
 DIST_INSTALL = True
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
+    CXXFLAGS += CONFIG['GLIB_CFLAGS']
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -421,19 +421,58 @@ XPCOMGlueLoadXULFunctions(const nsDynami
 }
 
 void
 XPCOMGlueEnablePreload()
 {
   do_preload = true;
 }
 
+#ifdef MOZ_WIDGET_GTK
+#include <glib.h>
+
+class GSliceInit {
+#if defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__)
+public:
+  GSliceInit() {
+    mHadGSlice = bool(getenv("G_SLICE"));
+    if (!mHadGSlice) {
+      // Disable the slice allocator, since jemalloc already uses similar layout
+      // algorithms, and using a sub-allocator tends to increase fragmentation.
+      // This must be done before g_thread_init() is called.
+      setenv("G_SLICE", "always-malloc", 1);
+    }
+  }
+
+  ~GSliceInit() {
+    if (mHadGSlice) {
+      return;
+    }
+    if (sTop) {
+      auto g_thread_init = (void (*)(void*)) GetSymbol(sTop->libHandle,
+        "g_thread_init");
+      auto g_type_init = (void (*)()) GetSymbol(sTop->libHandle, "g_type_init");
+      g_thread_init(nullptr); // For GLib version < 2.32
+      g_type_init(); // For 2.32 <= GLib version < 2.36
+    }
+    unsetenv("G_SLICE");
+  }
+
+private:
+  bool mHadGSlice;
+#endif
+};
+#endif
+
 nsresult
 XPCOMGlueStartup(const char* aXPCOMFile)
 {
+#ifdef MOZ_WIDGET_GTK
+  GSliceInit gSliceInit;
+#endif
   xpcomFunctions.version = XPCOM_GLUE_VERSION;
   xpcomFunctions.size    = sizeof(XPCOMFunctions);
 
   if (!aXPCOMFile) {
     aXPCOMFile = XPCOM_DLL;
   }
 
   GetFrozenFunctionsFunc func = XPCOMGlueLoad(aXPCOMFile);