Bug 1371079 - Use PRThread for IPC thread safety checking (r=dvander)
authorBill McCloskey <billm@mozilla.com>
Thu, 25 May 2017 16:51:31 -0700
changeset 363621 34adc718cf1fc6138a48d3d2c9dd37552bdbe00a
parent 363620 894903d3018309c413c75d3ba796b45c5094a25a
child 363622 ccc624eb77e1ccf5bd099fd2363010838ad429e4
push id32021
push usercbook@mozilla.com
push dateTue, 13 Jun 2017 10:10:08 +0000
treeherdermozilla-central@a8f8e440d627 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1371079
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 1371079 - Use PRThread for IPC thread safety checking (r=dvander) MozReview-Commit-ID: 9qRiC43LuVP
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -516,17 +516,17 @@ MessageChannel::MessageChannel(const cha
                                IToplevelProtocol *aListener)
   : mName(aName),
     mListener(aListener),
     mChannelState(ChannelClosed),
     mSide(UnknownSide),
     mLink(nullptr),
     mWorkerLoop(nullptr),
     mChannelErrorTask(nullptr),
-    mWorkerLoopID(-1),
+    mWorkerThread(nullptr),
     mTimeoutMs(kNoTimeout),
     mInTimeoutSecondHalf(false),
     mNextSeqno(0),
     mLastSendError(SyncSendError::SendSuccess),
     mDispatchingAsyncMessage(false),
     mDispatchingAsyncMessageNestedLevel(0),
     mTransactionStack(nullptr),
     mTimedOutMessageSeqno(0),
@@ -684,17 +684,17 @@ MessageChannel::WillDestroyCurrentMessag
 #endif
     MOZ_CRASH("MessageLoop destroyed before MessageChannel that's bound to it");
 #endif
 }
 
 void
 MessageChannel::Clear()
 {
-    // Don't clear mWorkerLoopID; we use it in AssertLinkThread() and
+    // Don't clear mWorkerThread; we use it in AssertLinkThread() and
     // AssertWorkerThread().
     //
     // Also don't clear mListener.  If we clear it, then sending a message
     // through this channel after it's Clear()'ed can cause this process to
     // crash.
     //
     // In practice, mListener owns the channel, so the channel gets deleted
     // before mListener.  But just to be safe, mListener is a weak pointer.
@@ -769,17 +769,17 @@ private:
 
 bool
 MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
 {
     NS_PRECONDITION(!mLink, "Open() called > once");
 
     mMonitor = new RefCountedMonitor();
     mWorkerLoop = MessageLoop::current();
-    mWorkerLoopID = mWorkerLoop->id();
+    mWorkerThread = GetCurrentVirtualThread();
     mWorkerLoop->AddDestructionObserver(this);
     mListener->SetIsMainThreadProtocol();
 
     if (!AbstractThread::GetCurrent()) {
         mWorkerLoop->AddDestructionObserver(
             new AbstractThreadWrapperCleanup(
                 MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
     }
@@ -855,17 +855,17 @@ MessageChannel::OnOpenAsSlave(MessageCha
     aTargetChan->mChannelState = ChannelConnected;
     aTargetChan->mMonitor->Notify();
 }
 
 void
 MessageChannel::CommonThreadOpenInit(MessageChannel *aTargetChan, Side aSide)
 {
     mWorkerLoop = MessageLoop::current();
-    mWorkerLoopID = mWorkerLoop->id();
+    mWorkerThread = GetCurrentVirtualThread();
     mWorkerLoop->AddDestructionObserver(this);
     mListener->SetIsMainThreadProtocol();
 
     if (!AbstractThread::GetCurrent()) {
         mWorkerLoop->AddDestructionObserver(
             new AbstractThreadWrapperCleanup(
                 MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
     }
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -21,16 +21,17 @@
 #include "mozilla/ipc/Neutering.h"
 #endif // defined(OS_WIN)
 #include "mozilla/ipc/Transport.h"
 #if defined(MOZ_CRASHREPORTER) && defined(OS_WIN)
 #include "mozilla/mozalloc_oom.h"
 #include "nsExceptionHandler.h"
 #endif
 #include "MessageLink.h"
+#include "nsThreadUtils.h"
 
 #include <deque>
 #include <functional>
 #include <map>
 #include <math.h>
 #include <stack>
 
 namespace mozilla {
@@ -500,28 +501,28 @@ class MessageChannel : HasResultCodes, M
     // Run on the not current thread.
     void NotifyChannelClosed();
     void NotifyMaybeChannelError();
 
   private:
     // Can be run on either thread
     void AssertWorkerThread() const
     {
-        MOZ_ASSERT(mWorkerLoopID != -1, "Channel hasn't been opened yet");
-        MOZ_RELEASE_ASSERT(mWorkerLoopID == MessageLoop::current()->id(),
+        MOZ_ASSERT(mWorkerThread, "Channel hasn't been opened yet");
+        MOZ_RELEASE_ASSERT(mWorkerThread == GetCurrentVirtualThread(),
                            "not on worker thread!");
     }
 
     // The "link" thread is either the I/O thread (ProcessLink) or the
     // other actor's work thread (ThreadLink).  In either case, it is
     // NOT our worker thread.
     void AssertLinkThread() const
     {
-        MOZ_ASSERT(mWorkerLoopID != -1, "Channel hasn't been opened yet");
-        MOZ_RELEASE_ASSERT(mWorkerLoopID != MessageLoop::current()->id(),
+        MOZ_ASSERT(mWorkerThread, "Channel hasn't been opened yet");
+        MOZ_RELEASE_ASSERT(mWorkerThread != GetCurrentVirtualThread(),
                            "on worker thread but should not be!");
     }
 
   private:
     class MessageTask :
         public CancelableRunnable,
         public LinkedListElement<RefPtr<MessageTask>>,
         public nsIRunnablePriority
@@ -571,19 +572,19 @@ class MessageChannel : HasResultCodes, M
     IToplevelProtocol* mListener;
     ChannelState mChannelState;
     RefPtr<RefCountedMonitor> mMonitor;
     Side mSide;
     MessageLink* mLink;
     MessageLoop* mWorkerLoop;           // thread where work is done
     RefPtr<CancelableRunnable> mChannelErrorTask;  // NotifyMaybeChannelError runnable
 
-    // id() of mWorkerLoop.  This persists even after mWorkerLoop is cleared
-    // during channel shutdown.
-    int mWorkerLoopID;
+    // Thread we are allowed to send and receive on. This persists even after
+    // mWorkerLoop is cleared during channel shutdown.
+    PRThread* mWorkerThread;
 
     // Timeout periods are broken up in two to prevent system suspension from
     // triggering an abort. This method (called by WaitForEvent with a 'did
     // timeout' flag) decides if we should wait again for half of mTimeoutMs
     // or give up.
     int32_t mTimeoutMs;
     bool mInTimeoutSecondHalf;