Bug 1371203 - Ensure channel object lives longer than the owned ChannelEventQueue. r=mayhemer
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 09 Jun 2017 19:59:41 +0800
changeset 411502 230564c469b24b9201ae815c6af0dd1670b5ad74
parent 411501 2a06ae79b84a66e4ff98bfb2fbea8b832bdf77cc
child 411503 cc20d9ee0ef908d0139c521988e0ae0564e90030
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1371203
milestone55.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 1371203 - Ensure channel object lives longer than the owned ChannelEventQueue. r=mayhemer MozReview-Commit-ID: BPNJuMsocrf
netwerk/ipc/ChannelEventQueue.cpp
netwerk/ipc/ChannelEventQueue.h
--- a/netwerk/ipc/ChannelEventQueue.cpp
+++ b/netwerk/ipc/ChannelEventQueue.cpp
@@ -138,19 +138,42 @@ ChannelEventQueue::ResumeInternal()
 
   if (!--mSuspendCount) {
     if (mEventQueue.IsEmpty()) {
       // Nothing in queue to flush, simply clear the flag.
       mSuspended = false;
       return;
     }
 
+    // Hold a strong reference of mOwner to avoid the channel release
+    // before CompleteResume was executed.
+    class CompleteResumeRunnable : public CancelableRunnable
+    {
+    public:
+      explicit CompleteResumeRunnable(ChannelEventQueue* aQueue, nsISupports* aOwner)
+        : mQueue(aQueue)
+        , mOwner(aOwner)
+      {
+      }
+
+      NS_IMETHOD Run() override
+      {
+        mQueue->CompleteResume();
+        return NS_OK;
+      }
+
+    private:
+      virtual ~CompleteResumeRunnable() {}
+
+      RefPtr<ChannelEventQueue> mQueue;
+      nsCOMPtr<nsISupports> mOwner;
+    };
+
     // Worker thread requires a CancelableRunnable.
-    RefPtr<Runnable> event =
-      NewCancelableRunnableMethod(this, &ChannelEventQueue::CompleteResume);
+    RefPtr<Runnable> event = new CompleteResumeRunnable(this, mOwner);
 
     nsCOMPtr<nsIEventTarget> target;
       target = mEventQueue[0]->GetEventTarget();
     MOZ_ASSERT(target);
 
     Unused << NS_WARN_IF(NS_FAILED(target->Dispatch(event.forget(),
                                                     NS_DISPATCH_NORMAL)));
   }
--- a/netwerk/ipc/ChannelEventQueue.h
+++ b/netwerk/ipc/ChannelEventQueue.h
@@ -291,22 +291,27 @@ ChannelEventQueue::MaybeFlushQueue()
 }
 
 // Ensures that RunOrEnqueue() will be collecting events during its lifetime
 // (letting caller know incoming IPDL msgs should be queued). Flushes the queue
 // when it goes out of scope.
 class MOZ_STACK_CLASS AutoEventEnqueuer
 {
  public:
-  explicit AutoEventEnqueuer(ChannelEventQueue *queue) : mEventQueue(queue) {
+  explicit AutoEventEnqueuer(ChannelEventQueue *queue)
+    : mEventQueue(queue)
+    , mOwner(queue->mOwner)
+  {
     mEventQueue->StartForcedQueueing();
   }
   ~AutoEventEnqueuer() {
     mEventQueue->EndForcedQueueing();
   }
  private:
   RefPtr<ChannelEventQueue> mEventQueue;
+  // Ensure channel object lives longer than ChannelEventQueue.
+  nsCOMPtr<nsISupports> mOwner;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif