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.
This commit is contained in:
Mike Hommey 2015-06-26 10:59:52 -07:00
parent 5051e091d5
commit 2e6cb09122
5 changed files with 78 additions and 10 deletions

View File

@ -231,6 +231,7 @@ static char **gQtOnlyArgv;
#endif
#if defined(MOZ_WIDGET_GTK)
#include <glib.h>
#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

View File

@ -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)

View File

@ -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__

View File

@ -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']

View File

@ -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 <glib.h>
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);