From 4e8def4afd3924a963dd1c8dcffebbde97bf048c Mon Sep 17 00:00:00 2001 From: "Chih-Kai (Patrick) Wang" Date: Wed, 29 Apr 2015 00:22:44 +0800 Subject: [PATCH] Bug 1155547 - Wait Nuwa forking a process if preallocated process isn't present. r=khuey --- dom/base/nsFrameLoader.cpp | 7 +++- dom/ipc/ContentParent.cpp | 19 +++++++++++ dom/ipc/PreallocatedProcessManager.cpp | 46 ++++++++++++++++++++++++++ dom/ipc/PreallocatedProcessManager.h | 1 + 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index f7436ae666c5..893d632b92bd 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -2276,7 +2276,12 @@ nsFrameLoader::TryRemoteBrowser() NS_ENSURE_TRUE(rv, false); nsCOMPtr ownerElement = mOwnerContent; - mRemoteBrowser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent); + TabParent* browser = ContentParent::CreateBrowserOrApp(context, ownerElement, openerContentParent); + if (mRemoteBrowser) { + MOZ_ASSERT(mRemoteBrowser == browser, "Must be the same as that obtained from another call"); + return false; + } + mRemoteBrowser = browser; if (!mRemoteBrowser) { return false; } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 7a0b2de82a1d..1735500190a8 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -703,7 +703,22 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp, /*out*/ bool* aTookPreAllocated) { MOZ_ASSERT(aApp); +#ifdef MOZ_NUWA_PROCESS + nsRefPtr process; + { + nsAutoString manifestURL; + if (NS_FAILED(aApp->GetManifestURL(manifestURL))) { + NS_ERROR("Failed to get manifest URL"); + return nullptr; + } + process = PreallocatedProcessManager::BlockForNewProcess(manifestURL); + if (!process) { + process = sAppContentParents->Get(manifestURL); + } + } +#else nsRefPtr process = PreallocatedProcessManager::Take(); +#endif if (process) { if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) { @@ -871,7 +886,11 @@ ContentParent::GetNewOrUsedBrowserProcess(bool aForBrowserElement, } // Try to take and transform the preallocated process into browser. +#ifdef MOZ_NUWA_PROCESS + nsRefPtr p = PreallocatedProcessManager::BlockForNewProcess(NS_LITERAL_STRING("")); +#else nsRefPtr p = PreallocatedProcessManager::Take(); +#endif if (p) { p->TransformPreallocatedIntoBrowser(aOpener); } else { diff --git a/dom/ipc/PreallocatedProcessManager.cpp b/dom/ipc/PreallocatedProcessManager.cpp index 02cd433acc2b..d9a803017aee 100644 --- a/dom/ipc/PreallocatedProcessManager.cpp +++ b/dom/ipc/PreallocatedProcessManager.cpp @@ -59,6 +59,7 @@ public: void OnNuwaReady(); bool PreallocatedProcessReady(); already_AddRefed GetSpareProcess(); + already_AddRefed BlockForNewProcess(const nsAString& aManifestURL); private: void NuwaFork(); @@ -72,6 +73,7 @@ private: // Nuwa process is ready for creating new process. bool mIsNuwaReady; + nsTArray mWaitingList; #endif private: @@ -283,6 +285,44 @@ PreallocatedProcessManagerImpl::GetSpareProcess() return process.forget(); } +already_AddRefed +PreallocatedProcessManagerImpl::BlockForNewProcess(const nsAString& aManifestURL) +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!mEnabled || !IsNuwaReady()) { + // If nuwa is not ready, we can't enter the nested loop. + return nullptr; + } + + if (mSpareProcesses.IsEmpty()) { + // a request comes in while there's no preallocated process. fork now. + if (aManifestURL.Length() == 0) { + // for browser. + NuwaFork(); + } else if (mWaitingList.IndexOf(aManifestURL) == nsTArray::NoIndex) { + // add the manifest url to waiting list. if there's another request came in while + // we are in nested loop, this will prevent later request from forking again. + NuwaFork(); + mWaitingList.AppendElement(aManifestURL); + } + while (mSpareProcesses.IsEmpty() && + (aManifestURL.Length() != 0 && + mWaitingList.IndexOf(aManifestURL) != nsTArray::NoIndex)) { + NS_ProcessNextEvent(); + } + // If we are no longer in the waiting list, just return and content parent will + // get a process for us. + if (aManifestURL.Length() != 0 && + mWaitingList.IndexOf(aManifestURL) == nsTArray::NoIndex) { + return nullptr; + } + mWaitingList.RemoveElement(aManifestURL); + } + + return GetSpareProcess(); +} + + /** * Publish a ContentParent to spare process list. */ @@ -484,6 +524,12 @@ PreallocatedProcessManager::PreallocatedProcessReady() return GetPPMImpl()->PreallocatedProcessReady(); } +/* static */ already_AddRefed +PreallocatedProcessManager::BlockForNewProcess(const nsAString& aManifestURL) +{ + return GetPPMImpl()->BlockForNewProcess(aManifestURL); +} + #endif } // namespace mozilla diff --git a/dom/ipc/PreallocatedProcessManager.h b/dom/ipc/PreallocatedProcessManager.h index 4df86726d693..0af173e8227b 100644 --- a/dom/ipc/PreallocatedProcessManager.h +++ b/dom/ipc/PreallocatedProcessManager.h @@ -84,6 +84,7 @@ public: static bool IsNuwaReady(); static void OnNuwaReady(); static bool PreallocatedProcessReady(); + static already_AddRefed BlockForNewProcess(const nsAString& aManifestURL); #endif private: