Bug 1103036 - Wait for ContentChild shutdown during profile-before-change; r=billm
authorJim Chen <nchen@mozilla.com>
Sat, 10 Jan 2015 13:42:10 -0500
changeset 223137 66083ac0f3c069c5b0bb4908b50cffb15d7d2eb6
parent 223136 ebb500eb92d8cbadf2bff07540b6cca70204c33d
child 223138 19017193859ab2cedee889654d106745f5f8f4a8
push id53827
push usernchen@mozilla.com
push dateSat, 10 Jan 2015 18:59:27 +0000
treeherdermozilla-inbound@a55f093defe1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1103036
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1103036 - Wait for ContentChild shutdown during profile-before-change; r=billm
dom/ipc/ContentParent.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -582,16 +582,17 @@ static uint64_t gContentChildID = 1;
 
 // We want the prelaunched process to know that it's for apps, but not
 // actually for any app in particular.  Use a magic manifest URL.
 // Can't be a static constant.
 #define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
 
 static const char* sObserverTopics[] = {
     "xpcom-shutdown",
+    "profile-before-change",
     NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
     "child-memory-reporter-request",
     "memory-pressure",
     "child-gc-request",
     "child-cc-request",
     "child-mmu-request",
     "last-pb-context-exited",
     "file-watcher-update",
@@ -1498,17 +1499,17 @@ ContentParent::TransformPreallocatedInto
 
 void
 ContentParent::ShutDownProcess(ShutDownMethod aMethod)
 {
     // Shutting down by sending a shutdown message works differently than the
     // other methods. We first call Shutdown() in the child. After the child is
     // ready, it calls FinishShutdown() on us. Then we close the channel.
     if (aMethod == SEND_SHUTDOWN_MESSAGE) {
-        if (mIPCOpen && SendShutdown()) {
+        if (mIPCOpen && !mShutdownPending && SendShutdown()) {
             mShutdownPending = true;
         }
 
         // If call was not successful, the channel must have been broken
         // somehow, and we will clean up the error in ActorDestroy.
         return;
     }
 
@@ -1769,18 +1770,18 @@ struct DelayedDeleteContentParentTask : 
 void
 ContentParent::ActorDestroy(ActorDestroyReason why)
 {
     if (mForceKillTimer) {
         mForceKillTimer->Cancel();
         mForceKillTimer = nullptr;
     }
 
-    // Signal shutdown completion regardless of error state,
-    // so we can finish waiting in the xpcom-shutdown observer.
+    // Signal shutdown completion regardless of error state, so we can
+    // finish waiting in the xpcom-shutdown/profile-before-change observer.
     mIPCOpen = false;
 
     if (why == NormalShutdown && !mCalledClose) {
         // If we shut down normally but haven't called Close, assume somebody
         // else called Close on us. In that case, we still need to call
         // ShutDownProcess below to perform other necessary clean up.
         mCalledClose = true;
     }
@@ -2740,20 +2741,20 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
 ContentParent::Observe(nsISupports* aSubject,
                        const char* aTopic,
                        const char16_t* aData)
 {
-    if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
-        if (!mShutdownPending && mIPCOpen) {
-            ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
-        }
+    if (mSubprocess && (!strcmp(aTopic, "profile-before-change") ||
+                        !strcmp(aTopic, "xpcom-shutdown"))) {
+        // Okay to call ShutDownProcess multiple times.
+        ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
 
         // 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.
         while (mIPCOpen) {
             NS_ProcessNextEvent(nullptr, true);
         }
         NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");