diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index c4220ffd385..45123127f5c 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -231,6 +231,7 @@ static char **gQtOnlyArgv; #endif #if defined(MOZ_WIDGET_GTK) +#include #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) #define CLEANUP_MEMORY 1 #define PANGO_ENABLE_BACKEND @@ -4287,6 +4288,25 @@ XREMain::XRE_mainRun() return rv; } +#if MOZ_WIDGET_GTK == 2 +void XRE_GlibInit() +{ + static bool ran_once = false; + + // glib < 2.24 doesn't want g_thread_init to be invoked twice, so ensure + // we only do it once. No need for thread safety here, since this is invoked + // well before any thread is spawned. + if (!ran_once) { + // glib version < 2.36 doesn't initialize g_slice in a static initializer. + // Ensure this happens through g_thread_init (glib version < 2.32) or + // g_type_init (2.32 <= gLib version < 2.36)." + g_thread_init(nullptr); + g_type_init(); + ran_once = true; + } +} +#endif + /* * XRE_main - A class based main entry point used by most platforms. * Note that on OSX, aAppData->xreDirectory will point to @@ -4325,14 +4345,8 @@ XREMain::XRE_main(int argc, char* argv[], const nsXREAppData* aAppData) 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); +#if MOZ_WIDGET_GTK == 2 + XRE_GlibInit(); #endif // init diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index b6fb2ecc293..d4a7c75e6c9 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -466,8 +466,8 @@ XRE_InitChildProcess(int aArgc, #ifdef MOZ_X11 XInitThreads(); #endif -#if defined(MOZ_WIDGET_GTK) - g_thread_init(nullptr); +#if MOZ_WIDGET_GTK == 2 + XRE_GlibInit(); #endif #if defined(MOZ_WIDGET_QT) diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index 975b7b21fa3..a4c0067bcd0 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -477,4 +477,9 @@ XRE_API(void, XRE_API(int, XRE_XPCShellMain, (int argc, char** argv, char** envp)) +#if MOZ_WIDGET_GTK == 2 +XRE_API(void, + XRE_GlibInit, ()) +#endif + #endif // _nsXULAppAPI_h__ diff --git a/xpcom/glue/standalone/moz.build b/xpcom/glue/standalone/moz.build index 47a2d6e0112..4f24c50a31d 100644 --- a/xpcom/glue/standalone/moz.build +++ b/xpcom/glue/standalone/moz.build @@ -54,3 +54,6 @@ USE_LIBS += [ NO_EXPAND_LIBS = True DIST_INSTALL = True + +if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): + CXXFLAGS += CONFIG['GLIB_CFLAGS'] diff --git a/xpcom/glue/standalone/nsXPCOMGlue.cpp b/xpcom/glue/standalone/nsXPCOMGlue.cpp index eac10e5f0e0..7654d64937e 100644 --- a/xpcom/glue/standalone/nsXPCOMGlue.cpp +++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -426,9 +426,55 @@ XPCOMGlueEnablePreload() do_preload = true; } +#if defined(MOZ_WIDGET_GTK) && (defined(MOZ_MEMORY) || defined(__FreeBSD__) || defined(__NetBSD__)) +#define MOZ_GSLICE_INIT +#endif + +#ifdef MOZ_GSLICE_INIT +#include + +class GSliceInit { +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. + // glib >= 2.36 initializes g_slice as a side effect of its various static + // initializers, so this needs to happen before glib is loaded, which is + // this is hooked in XPCOMGlueStartup before libxul is loaded. This + // relies on the main executable not depending on glib. + setenv("G_SLICE", "always-malloc", 1); + } + } + + ~GSliceInit() { +#if MOZ_WIDGET_GTK == 2 + if (sTop) { + auto XRE_GlibInit = (void (*)(void)) GetSymbol(sTop->libHandle, + "XRE_GlibInit"); + // Initialize glib enough for G_SLICE to have an effect before it is unset. + // unset. + XRE_GlibInit(); + } +#endif + if (!mHadGSlice) { + unsetenv("G_SLICE"); + } + } + +private: + bool mHadGSlice; +}; +#endif + nsresult XPCOMGlueStartup(const char* aXPCOMFile) { +#ifdef MOZ_GSLICE_INIT + GSliceInit gSliceInit; +#endif xpcomFunctions.version = XPCOM_GLUE_VERSION; xpcomFunctions.size = sizeof(XPCOMFunctions);