Bug 1369571 - break reference cycle between HttpChannelChild and HttpBackgroundChannelChild while PHttpChannel is destroyed. r=mayhemer
authorShih-Chiang Chien <schien@mozilla.com>
Tue, 18 Jul 2017 19:03:14 +0800
changeset 371654 039ee2964fb9f43765ff90564a9311f456a2ee16
parent 371653 49555e689cc8b55c56d413c88ffbe6a4d0e610fd
child 371655 5b08a1e39e2a06f1e49da8aff4f97379cdc667ba
push id32252
push userkwierso@gmail.com
push dateSat, 29 Jul 2017 00:17:07 +0000
treeherdermozilla-central@ec329722b2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmayhemer
bugs1369571
milestone56.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 1369571 - break reference cycle between HttpChannelChild and HttpBackgroundChannelChild while PHttpChannel is destroyed. r=mayhemer The reference cycle is supposed to be removed when HttpBackgroundChannelChild::ActorDestroyed, however this operation is pending due until HttpChannelChild receives OnStartRequest IPC message. Unfortunately the OnStartRequest IPC message is dropped because of PContent shutdown procedure. So, the reference removal is never executed, which leaks memory until content process is terminated. MozReview-Commit-ID: 7R6nt7W690o
netwerk/protocol/http/HttpBackgroundChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.cpp
@@ -114,16 +114,19 @@ HttpBackgroundChannelChild::Init(HttpCha
 void
 HttpBackgroundChannelChild::OnChannelClosed()
 {
   LOG(("HttpBackgroundChannelChild::OnChannelClosed [this=%p]\n", this));
   MOZ_ASSERT(OnSocketThread());
 
   // HttpChannelChild is not going to handle any incoming message.
   mChannelChild = nullptr;
+
+  // Remove pending IPC messages as well.
+  mQueuedRunnables.Clear();
 }
 
 void
 HttpBackgroundChannelChild::OnStartRequestReceived()
 {
   LOG(("HttpBackgroundChannelChild::OnStartRequestReceived [this=%p]\n", this));
   MOZ_ASSERT(OnSocketThread());
   MOZ_ASSERT(mChannelChild);
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -3600,10 +3600,23 @@ HttpChannelChild::ShouldInterceptURI(nsI
 
 mozilla::ipc::IPCResult
 HttpChannelChild::RecvSetPriority(const int16_t& aPriority)
 {
   mPriority = aPriority;
   return IPC_OK();
 }
 
+void
+HttpChannelChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // OnStartRequest might be dropped if IPDL is destroyed abnormally
+  // and BackgroundChild might have pending IPC messages.
+  // Clean up BackgroundChild at this time to prevent memleak.
+  if (aWhy != Deletion) {
+    CleanupBackgroundChannel();
+  }
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -160,16 +160,18 @@ protected:
   mozilla::ipc::IPCResult RecvReportSecurityMessage(const nsString& messageTag,
                                                     const nsString& messageCategory) override;
 
   mozilla::ipc::IPCResult RecvIssueDeprecationWarning(const uint32_t& warning,
                                                       const bool& asError) override;
 
   mozilla::ipc::IPCResult RecvSetPriority(const int16_t& aPriority) override;
 
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
   MOZ_MUST_USE bool
   GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
   virtual void DoNotifyListenerCleanup() override;
 
   NS_IMETHOD GetResponseSynthesized(bool* aSynthesized) override;
 
   nsresult
   AsyncCall(void (HttpChannelChild::*funcPtr)(),