Bug 683063, part 1: Don't delete ContentParent out from under the cleanup process. r=jdm
authorChris Jones <jones.chris.g@gmail.com>
Tue, 30 Aug 2011 21:11:25 -0700
changeset 76255 86f1809d81d79a98de7ddb7332869997f3bd359d
parent 76254 dba8b4d896407962453e32fdd2a408edaaae4bae
child 76256 c7e6f57e173220fddbd6a0542df2f2d03465edae
push id21087
push usermak77@bonardo.net
push dateWed, 31 Aug 2011 08:44:58 +0000
treeherdermozilla-central@c7e6f57e1732 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs683063
milestone9.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 683063, part 1: Don't delete ContentParent out from under the cleanup process. r=jdm
dom/ipc/ContentParent.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -264,23 +264,38 @@ ContentParent::OnChannelConnected(int32 
                 setpriority(PRIO_PROCESS, pid, getpriority(PRIO_PROCESS, pid) + nice);
             }
         }
 #endif
     }
 }
 
 namespace {
+
 void
 DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess)
 {
     XRE_GetIOMessageLoop()
         ->PostTask(FROM_HERE,
                    new DeleteTask<GeckoChildProcessHost>(aSubprocess));
 }
+
+// This runnable only exists to delegate ownership of the
+// ContentParent to this runnable, until it's deleted by the event
+// system.
+struct DelayedDeleteContentParentTask : public nsRunnable
+{
+    DelayedDeleteContentParentTask(ContentParent* aObj) : mObj(aObj) { }
+
+    // No-op
+    NS_IMETHODIMP Run() { return NS_OK; }
+
+    nsRefPtr<ContentParent> mObj;
+};
+
 }
 
 void
 ContentParent::ActorDestroy(ActorDestroyReason why)
 {
     nsCOMPtr<nsIThreadObserver>
         kungFuDeathGrip(static_cast<nsIThreadObserver*>(this));
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
@@ -361,16 +376,25 @@ ContentParent::ActorDestroy(ActorDestroy
             obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull);
         }
     }
 
     MessageLoop::current()->
         PostTask(FROM_HERE,
                  NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
     mSubprocess = NULL;
+
+    // IPDL rules require actors to live on past ActorDestroy, but it
+    // may be that the kungFuDeathGrip above is the last reference to
+    // |this|.  If so, when we go out of scope here, we're deleted and
+    // all hell breaks loose.
+    //
+    // This runnable ensures that a reference to |this| lives on at
+    // least until after the current task finishes running.
+    NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
 }
 
 TabParent*
 ContentParent::CreateTab(PRUint32 aChromeFlags)
 {
   return static_cast<TabParent*>(SendPBrowserConstructor(aChromeFlags));
 }