Bug 1313200 - Init AbstractThread properly and early. r?nfroyd draft
authorKan-Ru Chen <kanru@kanru.info>
Wed, 19 Apr 2017 13:24:09 +0800
changeset 565256 7f96694bda9b5da56995c03edb60c7dd9163ee0f
parent 564098 bb38d935d699e0529f9e0bb35578d381026415c4
child 565257 5ba21c7ff7632ab30422610cc782cd21e6908794
push id54821
push userbmo:kchen@mozilla.com
push dateWed, 19 Apr 2017 17:23:22 +0000
reviewersnfroyd
bugs1313200
milestone55.0a1
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
toolkit/xre/nsEmbedFunctions.cpp
xpcom/build/XPCOMInit.cpp
xpcom/threads/AbstractThread.cpp
xpcom/threads/AbstractThread.h
xpcom/threads/nsThreadManager.cpp
--- 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");