Bug 1637085: Use AsyncShutdown for ContentParent shutdown. r=nika

Differential Revision: https://phabricator.services.mozilla.com/D74746
This commit is contained in:
Kris Maglione 2020-06-02 20:46:07 +00:00
parent 1c96455b0f
commit 28deb15a56
2 changed files with 78 additions and 19 deletions

View File

@ -616,8 +616,6 @@ static bool sCreatedFirstContentProcess = false;
static uint64_t gContentChildID = 1;
static const char* sObserverTopics[] = {
"xpcom-shutdown",
"profile-before-change",
NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC,
NS_IPC_CAPTIVE_PORTAL_SET_STATE,
@ -1473,6 +1471,8 @@ void ContentParent::Init() {
}
}
AddShutdownBlockers();
// Flush any pref updates that happened during launch and weren't
// included in the blobs set up in BeginSubprocessLaunch.
for (const Pref& pref : mQueuedPrefs) {
@ -1724,6 +1724,8 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) {
// finish waiting in the xpcom-shutdown/profile-before-change observer.
mIPCOpen = false;
RemoveShutdownBlockers();
if (mHangMonitorActor) {
ProcessHangMonitor::RemoveProcess(mHangMonitorActor);
mHangMonitorActor = nullptr;
@ -3081,30 +3083,79 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback)
NS_INTERFACE_MAP_ENTRY(nsIAsyncShutdownBlocker)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentParent)
NS_INTERFACE_MAP_END
// Async shutdown blocker
NS_IMETHODIMP
ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (mSubprocess && (!strcmp(aTopic, "profile-before-change") ||
!strcmp(aTopic, "xpcom-shutdown"))) {
ContentParent::BlockShutdown(nsIAsyncShutdownClient* aClient) {
// Make sure that our process will get scheduled.
ProcessPriorityManager::SetProcessPriority(this,
PROCESS_PRIORITY_FOREGROUND);
ProcessPriorityManager::SetProcessPriority(this, PROCESS_PRIORITY_FOREGROUND);
// Okay to call ShutDownProcess multiple times.
ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
MarkAsDead();
// Wait for shutdown to complete, so that we receive any shutdown
// data (e.g. telemetry) from the child before we quit.
// This loop terminate prematurely based on mForceKillTimer.
SpinEventLoopUntil([&]() { return !mIPCOpen || mCalledKillHard; });
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
return NS_OK;
}
NS_IMETHODIMP
ContentParent::GetName(nsAString& aName) {
aName.AssignLiteral("ContentParent:");
aName.AppendPrintf(" id=%p", this);
return NS_OK;
}
NS_IMETHODIMP
ContentParent::GetState(nsIPropertyBag** aResult) {
auto props = MakeRefPtr<nsHashPropertyBag>();
props->SetPropertyAsAString(NS_LITERAL_STRING("remoteTypePrefix"),
RemoteTypePrefix(mRemoteType));
*aResult = props.forget().downcast<nsIWritablePropertyBag>().take();
return NS_OK;
}
static StaticRefPtr<nsIAsyncShutdownClient> sXPCOMShutdownClient;
static StaticRefPtr<nsIAsyncShutdownClient> sProfileBeforeChangeClient;
static void InitClients() {
if (!sXPCOMShutdownClient) {
nsresult rv;
nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
nsCOMPtr<nsIAsyncShutdownClient> client;
rv = svc->GetXpcomWillShutdown(getter_AddRefs(client));
sXPCOMShutdownClient = client.forget();
ClearOnShutdown(&sXPCOMShutdownClient);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "XPCOMShutdown shutdown blocker");
rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
sProfileBeforeChangeClient = client.forget();
ClearOnShutdown(&sProfileBeforeChangeClient);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv),
"profileBeforeChange shutdown blocker");
}
}
void ContentParent::AddShutdownBlockers() {
InitClients();
sXPCOMShutdownClient->AddBlocker(this, NS_LITERAL_STRING(__FILE__), __LINE__,
EmptyString());
sProfileBeforeChangeClient->AddBlocker(this, NS_LITERAL_STRING(__FILE__),
__LINE__, EmptyString());
}
void ContentParent::RemoveShutdownBlockers() {
Unused << sXPCOMShutdownClient->RemoveBlocker(this);
Unused << sProfileBeforeChangeClient->RemoveBlocker(this);
}
NS_IMETHODIMP
ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (IsDead() || !mSubprocess) {
return NS_OK;
}
@ -3545,6 +3596,8 @@ void ContentParent::KillHard(const char* aReason) {
mCalledKillHard = true;
mForceKillTimer = nullptr;
RemoveShutdownBlockers();
GeneratePairedMinidump(aReason);
nsDependentCString reason(aReason);

View File

@ -36,6 +36,7 @@
#include "nsPluginTags.h"
#include "nsFrameMessageManager.h"
#include "nsHashKeys.h"
#include "nsIAsyncShutdown.h"
#include "nsIContentParent.h"
#include "nsIInterfaceRequestor.h"
#include "nsIObserver.h"
@ -132,6 +133,7 @@ class ContentParent final
public nsIObserver,
public nsIDOMGeoPositionCallback,
public nsIDOMGeoPositionErrorCallback,
public nsIAsyncShutdownBlocker,
public nsIInterfaceRequestor,
public gfx::gfxVarReceiver,
public mozilla::LinkedListElement<ContentParent>,
@ -340,6 +342,7 @@ class ContentParent final
NS_DECL_NSIOBSERVER
NS_DECL_NSIDOMGEOPOSITIONCALLBACK
NS_DECL_NSIDOMGEOPOSITIONERRORCALLBACK
NS_DECL_NSIASYNCSHUTDOWNBLOCKER
NS_DECL_NSIINTERFACEREQUESTOR
/**
@ -704,6 +707,9 @@ class ContentParent final
sJSPluginContentParents;
static StaticAutoPtr<LinkedList<ContentParent>> sContentParents;
void AddShutdownBlockers();
void RemoveShutdownBlockers();
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
// Cached Mac sandbox params used when launching content processes.
static StaticAutoPtr<std::vector<std::string>> sMacSandboxParams;