Bug 1313200 - Init AbstractThread properly and early. r?nfroyd
Separate AbstractThread::InitTLS and
AbstractThread::InitMainThread. Init AbstractThread main thread when
init nsThreadManager. Init AbstractThread TLS for all content process
types because for plugin and gmp processes we are doing IPC even
without init XPCOM and for content process init XPCOM requires IPC.
MozReview-Commit-ID: DhLub23oZz8
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -52,16 +52,18 @@
#include "base/message_loop.h"
#include "base/process_util.h"
#include "chrome/common/child_process.h"
#if defined(MOZ_WIDGET_ANDROID)
#include "chrome/common/ipc_channel.h"
#include "mozilla/jni/Utils.h"
#endif // defined(MOZ_WIDGET_ANDROID)
+#include "mozilla/AbstractThread.h"
+
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/IOThreadChild.h"
#include "mozilla/ipc/ProcessChild.h"
#include "ScopedXREEmbed.h"
#include "mozilla/plugins/PluginProcessChild.h"
#include "mozilla/dom/ContentProcess.h"
@@ -414,16 +416,20 @@ XRE_InitChildProcess(int aArgc,
mozilla::LogModule::Init();
char aLocal;
GeckoProfilerInitRAII profiler(&aLocal);
PROFILER_LABEL("Startup", "XRE_InitChildProcess",
js::ProfileEntry::Category::OTHER);
+ // Ensure AbstractThread is minimally setup, so async IPC messages
+ // work properly.
+ AbstractThread::InitTLS();
+
// Complete 'task_t' exchange for Mac OS X. This structure has the same size
// regardless of architecture so we don't have any cross-arch issues here.
#ifdef XP_MACOSX
if (aArgc < 1)
return NS_ERROR_FAILURE;
const char* const mach_port_name = aArgv[--aArgc];
const int kTimeoutMs = 1000;
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -1,17 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "base/basictypes.h"
-#include "mozilla/AbstractThread.h"
#include "mozilla/Atomics.h"
#include "mozilla/Poison.h"
#include "mozilla/SharedThreadPool.h"
#include "mozilla/XPCOM.h"
#include "nsXULAppAPI.h"
#include "nsXPCOMPrivate.h"
#include "nsXPCOMCIDInternal.h"
@@ -676,19 +675,16 @@ NS_InitXPCOM2(nsIServiceManager** aResul
// Initialize the JS engine.
const char* jsInitFailureReason = JS_InitWithFailureDiagnostic();
if (jsInitFailureReason) {
NS_RUNTIMEABORT(jsInitFailureReason);
}
sInitializedJS = true;
- // Init AbstractThread.
- AbstractThread::InitStatics();
-
rv = nsComponentManagerImpl::gComponentManager->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(nsComponentManagerImpl::gComponentManager);
return rv;
}
if (aResult) {
NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager);
@@ -786,17 +782,16 @@ NS_InitMinimalXPCOM()
return rv;
}
// Global cycle collector initialization.
if (!nsCycleCollector_init()) {
return NS_ERROR_UNEXPECTED;
}
- AbstractThread::InitStatics();
SharedThreadPool::InitStatics();
mozilla::Telemetry::Init();
mozilla::HangMonitor::Startup();
mozilla::BackgroundHangMonitor::Startup();
return NS_OK;
}
--- a/xpcom/threads/AbstractThread.cpp
+++ b/xpcom/threads/AbstractThread.cpp
@@ -246,17 +246,25 @@ AbstractThread::RequiresTailDispatchFrom
AbstractThread*
AbstractThread::MainThread()
{
MOZ_ASSERT(sMainThread);
return sMainThread;
}
void
-AbstractThread::InitStatics()
+AbstractThread::InitTLS()
+{
+ if (!sCurrentThreadTLS.init()) {
+ MOZ_CRASH();
+ }
+}
+
+void
+AbstractThread::InitMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!sMainThread);
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
MOZ_DIAGNOSTIC_ASSERT(mainThread);
sMainThread = new EventTargetWrapper(mainThread.get(), /* aRequireTailDispatch = */ true);
ClearOnShutdown(&sMainThread);
--- a/xpcom/threads/AbstractThread.h
+++ b/xpcom/threads/AbstractThread.h
@@ -90,17 +90,18 @@ public:
virtual nsIEventTarget* AsEventTarget() { MOZ_CRASH("Not an event target!"); }
// Returns the non-DocGroup version of AbstractThread on the main thread.
// A DocGroup-versioned one is available in DispatcherTrait::AbstractThreadFor().
// Note: DispatcherTrait::AbstractThreadFor() SHALL be used when possible.
static AbstractThread* MainThread();
// Must be called exactly once during startup.
- static void InitStatics();
+ static void InitTLS();
+ static void InitMainThread();
void DispatchStateChange(already_AddRefed<nsIRunnable> aRunnable);
static void DispatchDirectTask(already_AddRefed<nsIRunnable> aRunnable);
// Create a runnable that will run |aRunnable| and drain the direct tasks
// generated by it.
virtual already_AddRefed<nsIRunnable>
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsThreadManager.h"
#include "nsThread.h"
#include "nsThreadUtils.h"
#include "nsIClassInfoImpl.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
+#include "mozilla/AbstractThread.h"
#include "mozilla/ThreadLocal.h"
#ifdef MOZ_CANARY
#include <fcntl.h>
#include <unistd.h>
#endif
#include "MainThreadIdlePeriod.h"
@@ -105,16 +106,20 @@ nsThreadManager::Init()
nsCOMPtr<nsIIdlePeriod> idlePeriod = new MainThreadIdlePeriod();
mMainThread->RegisterIdlePeriod(idlePeriod.forget());
}
// We need to keep a pointer to the current thread, so we can satisfy
// GetIsMainThread calls that occur post-Shutdown.
mMainThread->GetPRThread(&mMainPRThread);
+ // Init AbstractThread.
+ AbstractThread::InitTLS();
+ AbstractThread::InitMainThread();
+
mInitialized = true;
return NS_OK;
}
void
nsThreadManager::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread(), "shutdown not called from main thread");