Bug 1377471 - disconnect mChannelChild directly if ActorDestroy is triggered by shutdown. r?mayhemer draft
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 07 Jul 2017 18:10:56 +0800
changeset 607358 7fa9091974d5bad71ca81902ec74e9d5a4c1d8aa
parent 602698 0b5603017c25e943ba3ab97cb46d88adf1e6a3e4
child 637028 52a42e119a74e6f7080866b99388c0d5418df9d4
push id67984
push userschien@mozilla.com
push dateWed, 12 Jul 2017 08:33:54 +0000
reviewersmayhemer
bugs1377471
milestone56.0a1
Bug 1377471 - disconnect mChannelChild directly if ActorDestroy is triggered by shutdown. r?mayhemer HttpBackgroundChannelChild::ActorDestroy is always called on STS thread. However OnSocketThread will return wrong result during shutdown phase. In this case we need to use gSocketTransportService->IsOnCurrentThreadInfallible() to get correct result. In addition, we should disconnect mChannelChild immediately while ActorDestroy is not triggered by normal IPDL deletion to release HTTP channel as soon as possible. MozReview-Commit-ID: CD7v3efS4zf
netwerk/protocol/http/HttpBackgroundChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.cpp
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
@@ -430,37 +430,29 @@ HttpBackgroundChannelChild::RecvSetClass
 
   return IPC_OK();
 }
 
 void
 HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this));
-
-  if (!OnSocketThread()) {
-    // PBackgroundChild might be destroyed during shutdown and
-    // ActorDestroy will be called on main thread directly.
-    // Simply disconnect with HttpChannelChild to release memory.
-    mChannelChild = nullptr;
-    RefPtr<HttpBackgroundChannelChild> self = this;
-    mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
-      "HttpBackgroundChannelChild::ActorDestroyNonSTSThread", [self]() {
-        MOZ_ASSERT(NS_IsMainThread());
-        self->mChannelChild = nullptr;
-      }));
-    return;
-  }
-
-  MOZ_ASSERT(OnSocketThread());
+  // This function might be called during shutdown phase, so OnSocketThread()
+  // might return false even on STS thread. Use IsOnCurrentThreadInfallible()
+  // to get correct information.
+  MOZ_ASSERT(gSocketTransportService);
+  MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
 
   // Ensure all IPC messages received before ActorDestroy can be
   // handled correctly. If there is any pending IPC message, destroyed
   // mChannelChild until those messages are flushed.
-  if (!mQueuedRunnables.IsEmpty()) {
+  // If background channel is not closed by normal IPDL actor deletion,
+  // remove the HttpChannelChild reference and notify background channel
+  // destroyed immediately.
+  if (aWhy == Deletion && !mQueuedRunnables.IsEmpty()) {
     LOG(("  > pending until queued messages are flushed\n"));
     RefPtr<HttpBackgroundChannelChild> self = this;
     mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
       "HttpBackgroundChannelChild::ActorDestroy", [self]() {
         MOZ_ASSERT(NS_IsMainThread());
         RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget();
 
         if (channelChild) {
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -312,17 +312,21 @@ HttpChannelChild::OnBackgroundChildReady
     mBgInitFailCallback = nullptr;
   }
 }
 
 void
 HttpChannelChild::OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild)
 {
   LOG(("HttpChannelChild::OnBackgroundChildDestroyed [this=%p]\n", this));
-  MOZ_ASSERT(OnSocketThread());
+  // This function might be called during shutdown phase, so OnSocketThread()
+  // might return false even on STS thread. Use IsOnCurrentThreadInfallible()
+  // to get correct information.
+  MOZ_ASSERT(gSocketTransportService);
+  MOZ_ASSERT(gSocketTransportService->IsOnCurrentThreadInfallible());
 
   nsCOMPtr<nsIRunnable> callback;
   {
     MutexAutoLock lock(mBgChildMutex);
 
     // mBgChild might be removed or replaced while the original background
     // channel is destroyed on STS thread.
     if (aBgChild != mBgChild) {