Bug 1362732 - Only delete AbstractThread wrapper when MessageLoop is about to destroy. r=billm
authorKan-Ru Chen <kanru@kanru.info>
Mon, 08 May 2017 14:14:32 +0800
changeset 357732 b3c7773fcef04e2c0b8fcd39323a9b899718fe84
parent 357731 7192279cfc4ac84455ebfc04608cb88a13a4d690
child 357733 e447a0ae5dba59f74f8b2ef426211f6ce3eb8739
push id31800
push userarchaeopteryx@coole-files.de
push dateThu, 11 May 2017 14:51:27 +0000
treeherdermozilla-central@0259418f19ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1362732
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 1362732 - Only delete AbstractThread wrapper when MessageLoop is about to destroy. r=billm The wrapper should have the same liftime as the underlying MessageLoop. This patch use the MessageLoop's DestructionObserver to manage the lifetime of the wrapper. MozReview-Commit-ID: 44ps4TKl3yQ
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -741,28 +741,47 @@ MessageChannel::Clear()
     mMaybeDeferredPendingCount = 0;
 
     mOutOfTurnReplies.clear();
     while (!mDeferred.empty()) {
         mDeferred.pop();
     }
 }
 
+class AbstractThreadWrapperCleanup : public MessageLoop::DestructionObserver
+{
+public:
+    explicit AbstractThreadWrapperCleanup(already_AddRefed<AbstractThread> aWrapper)
+        : mWrapper(aWrapper)
+    {}
+    virtual ~AbstractThreadWrapperCleanup() override {}
+    virtual void WillDestroyCurrentMessageLoop() override
+    {
+        mWrapper = nullptr;
+        MessageLoop::current()->RemoveDestructionObserver(this);
+        delete this;
+    }
+private:
+    RefPtr<AbstractThread> mWrapper;
+};
+
 bool
 MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
 {
     NS_PRECONDITION(!mLink, "Open() called > once");
 
     mMonitor = new RefCountedMonitor();
     mWorkerLoop = MessageLoop::current();
     mWorkerLoopID = mWorkerLoop->id();
     mWorkerLoop->AddDestructionObserver(this);
 
     if (!AbstractThread::GetCurrent()) {
-        mAbstractThread = MessageLoopAbstractThreadWrapper::Create(mWorkerLoop);
+        mWorkerLoop->AddDestructionObserver(
+            new AbstractThreadWrapperCleanup(
+                MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
     }
 
 
     ProcessLink *link = new ProcessLink(this);
     link->Open(aTransport, aIOLoop, aSide); // :TODO: n.b.: sets mChild
     mLink = link;
     return true;
 }
@@ -835,17 +854,19 @@ MessageChannel::OnOpenAsSlave(MessageCha
 void
 MessageChannel::CommonThreadOpenInit(MessageChannel *aTargetChan, Side aSide)
 {
     mWorkerLoop = MessageLoop::current();
     mWorkerLoopID = mWorkerLoop->id();
     mWorkerLoop->AddDestructionObserver(this);
 
     if (!AbstractThread::GetCurrent()) {
-        mAbstractThread = MessageLoopAbstractThreadWrapper::Create(mWorkerLoop);
+        mWorkerLoop->AddDestructionObserver(
+            new AbstractThreadWrapperCleanup(
+                MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
     }
 
     mLink = new ThreadLink(this, aTargetChan);
     mSide = aSide;
 }
 
 bool
 MessageChannel::Echo(Message* aMsg)
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -29,18 +29,16 @@
 
 #include <deque>
 #include <functional>
 #include <map>
 #include <math.h>
 #include <stack>
 
 namespace mozilla {
-class AbstractThread;
-
 namespace ipc {
 
 class MessageChannel;
 class IToplevelProtocol;
 
 class RefCountedMonitor : public Monitor
 {
   public:
@@ -553,17 +551,16 @@ class MessageChannel : HasResultCodes, M
     // Based on presumption the listener owns and overlives the channel,
     // this is never nullified.
     IToplevelProtocol* mListener;
     ChannelState mChannelState;
     RefPtr<RefCountedMonitor> mMonitor;
     Side mSide;
     MessageLink* mLink;
     MessageLoop* mWorkerLoop;           // thread where work is done
-    RefPtr<AbstractThread> mAbstractThread;
     RefPtr<CancelableRunnable> mChannelErrorTask;  // NotifyMaybeChannelError runnable
 
     // id() of mWorkerLoop.  This persists even after mWorkerLoop is cleared
     // during channel shutdown.
     int mWorkerLoopID;
 
     // Timeout periods are broken up in two to prevent system suspension from
     // triggering an abort. This method (called by WaitForEvent with a 'did