Bug 1320744 - Part 1, make refcounter of HttpChannelChild thread-safe. r?mayhemer draft
authorShih-Chiang Chien <schien@mozilla.com>
Thu, 19 Jan 2017 11:03:18 +0800
changeset 463436 d2ed3fc13b8fb7ffd81c942db9bb9969bab82bfc
parent 461121 8eaf154b385bbe0ff06155294ccf7962aa2d3324
child 463437 01e1c15912b030375b3ea82ca726a723566a6ba6
push id42063
push userschien@mozilla.com
push dateThu, 19 Jan 2017 03:13:40 +0000
reviewersmayhemer
bugs1320744
milestone53.0a1
Bug 1320744 - Part 1, make refcounter of HttpChannelChild thread-safe. r?mayhemer MozReview-Commit-ID: 5Br1WLlpvcR
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -193,44 +193,42 @@ HttpChannelChild::~HttpChannelChild()
 {
   LOG(("Destroying HttpChannelChild @%x\n", this));
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsISupports
 //-----------------------------------------------------------------------------
 
-// Override nsHashPropertyBag's AddRef: we don't need thread-safe refcnt
 NS_IMPL_ADDREF(HttpChannelChild)
 
 NS_IMETHODIMP_(MozExternalRefCountType) HttpChannelChild::Release()
 {
-  NS_PRECONDITION(0 != mRefCnt, "dup release");
-  NS_ASSERT_OWNINGTHREAD(HttpChannelChild);
-  --mRefCnt;
-  NS_LOG_RELEASE(this, mRefCnt, "HttpChannelChild");
+  nsrefcnt count = --mRefCnt;
+  MOZ_ASSERT(int32_t(count) >= 0, "dup release");
+  NS_LOG_RELEASE(this, count, "HttpChannelChild");
 
   // Normally we Send_delete in OnStopRequest, but when we need to retain the
   // remote channel for security info IPDL itself holds 1 reference, so we
   // Send_delete when refCnt==1.  But if !mIPCOpen, then there's nobody to send
   // to, so we fall through.
-  if (mKeptAlive && mRefCnt == 1 && mIPCOpen) {
+  if (mKeptAlive && count == 1 && mIPCOpen) {
     mKeptAlive = false;
     // We send a message to the parent, which calls SendDelete, and then the
     // child calling Send__delete__() to finally drop the refcount to 0.
     SendDeletingChannel();
     return 1;
   }
 
-  if (mRefCnt == 0) {
+  if (count == 0) {
     mRefCnt = 1; /* stabilize */
     delete this;
     return 0;
   }
-  return mRefCnt;
+  return count;
 }
 
 NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
   NS_INTERFACE_MAP_ENTRY(nsIRequest)
   NS_INTERFACE_MAP_ENTRY(nsIChannel)
   NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
   NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
@@ -2832,16 +2830,31 @@ HttpChannelChild::ResetInterception()
 NS_IMETHODIMP
 HttpChannelChild::GetResponseSynthesized(bool* aSynthesized)
 {
   NS_ENSURE_ARG_POINTER(aSynthesized);
   *aSynthesized = mSynthesizedResponse;
   return NS_OK;
 }
 
+bool
+HttpChannelChild::SendDeletingChannel()
+{
+  if (NS_IsMainThread()) {
+    return PHttpChannelChild::SendDeletingChannel();
+  }
+
+  nsresult rv;
+  rv = NS_DispatchToMainThread(
+         NewRunnableMethod(this, &HttpChannelChild::SendDeletingChannel));
+  MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+  return NS_SUCCEEDED(rv);
+}
+
 void
 HttpChannelChild::OverrideWithSynthesizedResponse(nsAutoPtr<nsHttpResponseHead>& aResponseHead,
                                                   nsIInputStream* aSynthesizedInput,
                                                   InterceptStreamListener* aStreamListener)
 {
   mInterceptListener = aStreamListener;
 
   // Intercepted responses should already be decoded.  If its a redirect,
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -104,16 +104,18 @@ public:
   void ReleaseIPDLReference();
 
   bool IsSuspended();
 
   mozilla::ipc::IPCResult RecvNotifyTrackingProtectionDisabled() override;
   mozilla::ipc::IPCResult RecvNotifyTrackingResource() override;
   void FlushedForDiversion();
 
+  bool SendDeletingChannel();
+
 protected:
   mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& channelStatus,
                                              const nsHttpResponseHead& responseHead,
                                              const bool& useResponseHead,
                                              const nsHttpHeaderArray& requestHeaders,
                                              const bool& isFromCache,
                                              const bool& cacheEntryAvailable,
                                              const uint32_t& cacheExpirationTime,