Bug 581341 - Part 4: Always run the IPC testshell callback, regardless of execution success or failure. r=bent
authorJosh Matthews <josh@joshmatthews.net>
Thu, 23 Jun 2011 19:31:58 -0400
changeset 79572 14e35982be4f766d96c0086406ac317d3410a007
parent 79571 82079836b062e9451eca3334f37f2d75f63671ba
child 79573 9b851182cd64c6176835e9b8b5b8a139aecff6f0
push id90
push userffxbld
push dateSun, 29 Jan 2012 07:46:52 +0000
treeherdermozilla-release@acddb6b6a01c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs581341
milestone10.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 581341 - Part 4: Always run the IPC testshell callback, regardless of execution success or failure. r=bent
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
ipc/testshell/TestShellParent.cpp
ipc/testshell/TestShellParent.h
toolkit/xre/nsEmbedFunctions.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -397,16 +397,24 @@ ContentParent::CreateTestShell()
 }
 
 bool
 ContentParent::DestroyTestShell(TestShellParent* aTestShell)
 {
     return PTestShellParent::Send__delete__(aTestShell);
 }
 
+TestShellParent*
+ContentParent::GetTestShellSingleton()
+{
+    if (!ManagedPTestShellParent().Length())
+        return nsnull;
+    return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
+}
+
 ContentParent::ContentParent()
     : mGeolocationWatchID(-1)
     , mRunToCompletionDepth(0)
     , mShouldCallUnblockChild(false)
     , mIsAlive(true)
     , mSendPermissionUpdates(false)
 {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -86,16 +86,17 @@ public:
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
     NS_DECL_NSIDEVICEMOTIONLISTENER
 
     TabParent* CreateTab(PRUint32 aChromeFlags);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
+    TestShellParent* GetTestShellSingleton();
 
     void ReportChildAlreadyBlocked();
     bool RequestRunToCompletion();
 
     bool IsAlive();
 
     void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report);
 
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -141,8 +141,23 @@ TestShellCommandParent::RunCallback(cons
   return JS_TRUE;
 }
 
 void
 TestShellCommandParent::ReleaseCallback()
 {
   mCallback.Release();
 }
+
+bool
+TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
+{
+  return static_cast<TestShellParent*>(Manager())->CommandDone(
+      this, aResponse);
+}
+
+void
+TestShellCommandParent::ActorDestroy(ActorDestroyReason why)
+{
+  if (why == AbnormalShutdown) {
+    ExecuteCallback(EmptyString());
+  }
+}
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -87,19 +87,22 @@ public:
   JSBool SetCallback(JSContext* aCx,
                      jsval aCallback);
 
   JSBool RunCallback(const nsString& aResponse);
 
   void ReleaseCallback();
 
 protected:
+  bool ExecuteCallback(const nsString& aResponse);
+
+  void ActorDestroy(ActorDestroyReason why);
+  
   bool Recv__delete__(const nsString& aResponse) {
-    return static_cast<TestShellParent*>(Manager())->CommandDone(
-      this, aResponse);
+    return ExecuteCallback(aResponse);
   }
 
 private:
   JSContext* mCx;
   nsAutoJSValHolder mCallback;
 };
 
 
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -707,26 +707,29 @@ XRE_ShutdownChildProcess()
       // that case, we fire off an Exit() here.  If we were indeed
       // above MessagePump::Run(), this Exit() is just superfluous.
       appShell->Exit();
   }
 #endif // XP_MACOSX
 }
 
 namespace {
-TestShellParent* gTestShellParent = nsnull;
+ContentParent* gContentParent; //long-lived, manually refcounted
 TestShellParent* GetOrCreateTestShellParent()
 {
-    if (!gTestShellParent) {
-        ContentParent* parent = ContentParent::GetNewOrUsed();
-        NS_ENSURE_TRUE(parent, nsnull);
-        gTestShellParent = parent->CreateTestShell();
-        NS_ENSURE_TRUE(gTestShellParent, nsnull);
+    if (!gContentParent) {
+        NS_ADDREF(gContentParent = ContentParent::GetNewOrUsed());
+    } else if (!gContentParent->IsAlive()) {
+        return nsnull;
     }
-    return gTestShellParent;
+    TestShellParent* tsp = gContentParent->GetTestShellSingleton();
+    if (!tsp) {
+        tsp = gContentParent->CreateTestShell();
+    }
+    return tsp;
 }
 }
 
 bool
 XRE_SendTestShellCommand(JSContext* aCx,
                          JSString* aCommand,
                          void* aCallback)
 {
@@ -755,20 +758,26 @@ XRE_GetChildGlobalObject(JSContext* aCx,
 {
     TestShellParent* tsp = GetOrCreateTestShellParent();
     return tsp && tsp->GetGlobalJSObject(aCx, aGlobalP);
 }
 
 bool
 XRE_ShutdownTestShell()
 {
-  if (!gTestShellParent)
-    return true;
-  return static_cast<ContentParent*>(gTestShellParent->Manager())->
-    DestroyTestShell(gTestShellParent);
+    if (!gContentParent) {
+        return true;
+    }
+    bool ret = true;
+    if (gContentParent->IsAlive()) {
+        ret = gContentParent->DestroyTestShell(
+            gContentParent->GetTestShellSingleton());
+    }
+    NS_RELEASE(gContentParent);
+    return ret;
 }
 
 #ifdef MOZ_X11
 void
 XRE_InstallX11ErrorHandler()
 {
   InstallX11ErrorHandler();
 }