Bug 1641211: Clear crashed processes from the e10s preallocator. r=jesup, a=RyanVM FIREFOX_78_0_BUILD1
authorKris Maglione <maglione.k@gmail.com>
Thu, 18 Jun 2020 14:17:37 -0700
changeset 600872 af00ea74f8fb2c6c92c98d866614872dd8b31028
parent 600871 3d86a2c337d1b67cfc42a93225d3227278535658
child 600873 1c385297d8fa1c2afdd4777fa61415d61054fd95
push id2362
push userryanvm@gmail.com
push dateMon, 22 Jun 2020 23:05:09 +0000
treeherdermozilla-release@af00ea74f8fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, RyanVM
bugs1641211
milestone78.0
Bug 1641211: Clear crashed processes from the e10s preallocator. r=jesup, a=RyanVM Differential Revision: https://phabricator.services.mozilla.com/D80518
dom/ipc/ContentParent.cpp
dom/ipc/PreallocatedProcessManager.cpp
dom/ipc/PreallocatedProcessManager.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -158,16 +158,17 @@
 #include "nsConsoleMessage.h"
 #include "nsConsoleService.h"
 #include "nsContentPermissionHelper.h"
 #include "nsContentUtils.h"
 #include "nsDebugImpl.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDocShell.h"
 #include "nsEmbedCID.h"
+#include "nsFocusManager.h"
 #include "nsFrameLoader.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashPropertyBag.h"
 #include "nsHyphenationManager.h"
 #include "nsIAlertsService.h"
 #include "nsIAppStartup.h"
 #include "nsIAppWindow.h"
 #include "nsIAsyncInputStream.h"
@@ -854,16 +855,17 @@ already_AddRefed<ContentParent> ContentP
 
   // Try to take the preallocated process only for the default process type.
   // The preallocated process manager might not had the chance yet to release
   // the process after a very recent ShutDownProcess, let's make sure we don't
   // try to reuse a process that is being shut down.
   RefPtr<ContentParent> p;
   if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
       (p = PreallocatedProcessManager::Take()) && !p->mShutdownPending) {
+    MOZ_DIAGNOSTIC_ASSERT(!p->IsDead());
     // For pre-allocated process we have not set the opener yet.
     p->mOpener = aOpener;
     aContentParents.AppendElement(p);
     p->mActivateTS = TimeStamp::Now();
     return p.forget();
   }
 
   return nullptr;
@@ -1553,16 +1555,18 @@ void ContentParent::RemoveFromList() {
   }
 }
 
 void ContentParent::MarkAsDead() {
   if (!mShutdownPending) {
     RemoveFromList();
   }
 
+  PreallocatedProcessManager::Erase(this);
+
 #ifdef MOZ_WIDGET_ANDROID
   if (mLifecycleState == LifecycleState::ALIVE) {
     nsCOMPtr<nsIEventTarget> launcherThread(GetIPCLauncher());
     MOZ_ASSERT(launcherThread);
 
     auto procType = java::GeckoProcessType::CONTENT();
     auto selector =
         java::GeckoProcessManager::Selector::New(procType, OtherPid());
--- a/dom/ipc/PreallocatedProcessManager.cpp
+++ b/dom/ipc/PreallocatedProcessManager.cpp
@@ -31,16 +31,17 @@ class PreallocatedProcessManagerImpl fin
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   // See comments on PreallocatedProcessManager for these methods.
   void AddBlocker(ContentParent* aParent);
   void RemoveBlocker(ContentParent* aParent);
   already_AddRefed<ContentParent> Take();
   bool Provide(ContentParent* aParent);
+  void Erase(ContentParent* aParent);
 
  private:
   static const char* const kObserverTopics[];
 
   static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
 
   PreallocatedProcessManagerImpl();
   ~PreallocatedProcessManagerImpl();
@@ -53,29 +54,26 @@ class PreallocatedProcessManagerImpl fin
   void AllocateOnIdle();
   void AllocateNow();
 
   void RereadPrefs();
   void Enable();
   void Disable();
   void CloseProcess();
 
-  void ObserveProcessShutdown(nsISupports* aSubject);
-
   bool mEnabled;
   bool mShutdown;
   bool mLaunchInProgress;
   RefPtr<ContentParent> mPreallocatedProcess;
   nsTHashtable<nsUint64HashKey> mBlockers;
 
   bool IsEmpty() const { return !mPreallocatedProcess && !mLaunchInProgress; }
 };
 
 const char* const PreallocatedProcessManagerImpl::kObserverTopics[] = {
-    "ipc:content-shutdown",
     "memory-pressure",
     "profile-change-teardown",
     NS_XPCOM_SHUTDOWN_OBSERVER_ID,
 };
 
 /* static */
 StaticRefPtr<PreallocatedProcessManagerImpl>
     PreallocatedProcessManagerImpl::sSingleton;
@@ -115,19 +113,17 @@ void PreallocatedProcessManagerImpl::Ini
   }
   RereadPrefs();
 }
 
 NS_IMETHODIMP
 PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
                                         const char* aTopic,
                                         const char16_t* aData) {
-  if (!strcmp("ipc:content-shutdown", aTopic)) {
-    ObserveProcessShutdown(aSubject);
-  } else if (!strcmp("nsPref:changed", aTopic)) {
+  if (!strcmp("nsPref:changed", aTopic)) {
     // The only other observer we registered was for our prefs.
     RereadPrefs();
   } else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic) ||
              !strcmp("profile-change-teardown", aTopic)) {
     Preferences::RemoveObserver(this, "dom.ipc.processPrelaunch.enabled");
     Preferences::RemoveObserver(this, "dom.ipc.processCount");
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     MOZ_ASSERT(os);
@@ -186,16 +182,23 @@ bool PreallocatedProcessManagerImpl::Pro
   }
 
   // We might get a call from both NotifyTabDestroying and NotifyTabDestroyed
   // with the same ContentParent. Returning true here for both calls is
   // important to avoid the cached process to be destroyed.
   return aParent == mPreallocatedProcess;
 }
 
+void PreallocatedProcessManagerImpl::Erase(ContentParent* aParent) {
+  if (mPreallocatedProcess == aParent) {
+    mBlockers.RemoveEntry(aParent->ChildID());
+    mPreallocatedProcess = nullptr;
+  }
+}
+
 void PreallocatedProcessManagerImpl::Enable() {
   if (mEnabled) {
     return;
   }
 
   mEnabled = true;
   AllocateAfterDelay();
 }
@@ -289,32 +292,16 @@ void PreallocatedProcessManagerImpl::Dis
 
 void PreallocatedProcessManagerImpl::CloseProcess() {
   if (mPreallocatedProcess) {
     mPreallocatedProcess->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
     mPreallocatedProcess = nullptr;
   }
 }
 
-void PreallocatedProcessManagerImpl::ObserveProcessShutdown(
-    nsISupports* aSubject) {
-  nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
-  NS_ENSURE_TRUE_VOID(props);
-
-  uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
-  props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
-  NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
-
-  if (mPreallocatedProcess && childID == mPreallocatedProcess->ChildID()) {
-    mPreallocatedProcess = nullptr;
-  }
-
-  mBlockers.RemoveEntry(childID);
-}
-
 inline PreallocatedProcessManagerImpl* GetPPMImpl() {
   return PreallocatedProcessManagerImpl::Singleton();
 }
 
 /* static */
 void PreallocatedProcessManager::AddBlocker(ContentParent* aParent) {
   GetPPMImpl()->AddBlocker(aParent);
 }
@@ -329,9 +316,14 @@ already_AddRefed<ContentParent> Prealloc
   return GetPPMImpl()->Take();
 }
 
 /* static */
 bool PreallocatedProcessManager::Provide(ContentParent* aParent) {
   return GetPPMImpl()->Provide(aParent);
 }
 
+/* static */
+void PreallocatedProcessManager::Erase(ContentParent* aParent) {
+  return GetPPMImpl()->Erase(aParent);
+}
+
 }  // namespace mozilla
--- a/dom/ipc/PreallocatedProcessManager.h
+++ b/dom/ipc/PreallocatedProcessManager.h
@@ -4,16 +4,17 @@
  * 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/. */
 
 #ifndef mozilla_PreallocatedProcessManager_h
 #define mozilla_PreallocatedProcessManager_h
 
 #include "base/basictypes.h"
 #include "mozilla/AlreadyAddRefed.h"
+#include "nsStringFwd.h"
 
 namespace mozilla {
 namespace dom {
 class ContentParent;
 }  // namespace dom
 
 /**
  * This class manages a ContentParent that it starts up ahead of any particular
@@ -49,16 +50,17 @@ class PreallocatedProcessManager final {
    *
    * After you Take() the preallocated process, you need to call one of the
    * Allocate* functions (or change the dom.ipc.processPrelaunch pref from
    * false to true) before we'll create a new process.
    */
   static already_AddRefed<ContentParent> Take();
 
   static bool Provide(ContentParent* aParent);
+  static void Erase(ContentParent* aParent);
 
  private:
   PreallocatedProcessManager();
   DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
 };
 
 }  // namespace mozilla