Bug 1155547 - Wait Nuwa forking a process if preallocated process isn't present. r=khuey

This commit is contained in:
Chih-Kai (Patrick) Wang 2015-04-29 00:22:44 +08:00
parent ce1e17ca98
commit 34da17d64f
4 changed files with 72 additions and 1 deletions

View File

@ -2276,7 +2276,12 @@ nsFrameLoader::TryRemoteBrowser()
NS_ENSURE_TRUE(rv, false);
nsCOMPtr<Element> 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;
}

View File

@ -703,7 +703,22 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp,
/*out*/ bool* aTookPreAllocated)
{
MOZ_ASSERT(aApp);
#ifdef MOZ_NUWA_PROCESS
nsRefPtr<ContentParent> 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<ContentParent> 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<ContentParent> p = PreallocatedProcessManager::BlockForNewProcess(NS_LITERAL_STRING(""));
#else
nsRefPtr<ContentParent> p = PreallocatedProcessManager::Take();
#endif
if (p) {
p->TransformPreallocatedIntoBrowser(aOpener);
} else {

View File

@ -59,6 +59,7 @@ public:
void OnNuwaReady();
bool PreallocatedProcessReady();
already_AddRefed<ContentParent> GetSpareProcess();
already_AddRefed<ContentParent> BlockForNewProcess(const nsAString& aManifestURL);
private:
void NuwaFork();
@ -72,6 +73,7 @@ private:
// Nuwa process is ready for creating new process.
bool mIsNuwaReady;
nsTArray<nsString> mWaitingList;
#endif
private:
@ -283,6 +285,44 @@ PreallocatedProcessManagerImpl::GetSpareProcess()
return process.forget();
}
already_AddRefed<ContentParent>
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<nsString>::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<nsString>::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<nsString>::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<ContentParent>
PreallocatedProcessManager::BlockForNewProcess(const nsAString& aManifestURL)
{
return GetPPMImpl()->BlockForNewProcess(aManifestURL);
}
#endif
} // namespace mozilla

View File

@ -84,6 +84,7 @@ public:
static bool IsNuwaReady();
static void OnNuwaReady();
static bool PreallocatedProcessReady();
static already_AddRefed<ContentParent> BlockForNewProcess(const nsAString& aManifestURL);
#endif
private: