Bug 1191143 - Cancel CPOWs from both sides (r=dvander)
authorBill McCloskey <billm@mozilla.com>
Mon, 13 Jul 2015 14:14:13 -0700
changeset 265101 52e0192973b32061b54b34c8154825bc6bc3b00a
parent 265100 56db457aef33a889004f51a6211f174aa12cca2d
child 265102 344cb85a558f538d70fc66602c3386ee7b4a885d
push id29456
push usercbook@mozilla.com
push dateWed, 30 Sep 2015 10:48:50 +0000
treeherdermozilla-central@97e537f85183 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1191143
milestone44.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 1191143 - Cancel CPOWs from both sides (r=dvander)
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -101,17 +101,17 @@ struct RunnableMethodTraits<mozilla::ipc
 };
 
 #define IPC_ASSERT(_cond, ...)                                      \
     do {                                                            \
         if (!(_cond))                                               \
             DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__);  \
     } while (0)
 
-static MessageChannel* gParentProcessBlocker;
+static MessageChannel* gMainThreadBlocker;
 
 namespace mozilla {
 namespace ipc {
 
 const int32_t MessageChannel::kNoTimeout = INT32_MIN;
 
 // static
 bool MessageChannel::sIsPumpingMessages = false;
@@ -399,18 +399,18 @@ MessageChannel::Clear()
     //
     // 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.
 
-    if (gParentProcessBlocker == this) {
-        gParentProcessBlocker = nullptr;
+    if (gMainThreadBlocker == this) {
+        gMainThreadBlocker = nullptr;
     }
 
     mDequeueOneTask->Cancel();
 
     mWorkerLoop = nullptr;
     delete mLink;
     mLink = nullptr;
 
@@ -1329,17 +1329,17 @@ MessageChannel::DispatchSyncMessage(cons
     // We don't want to run any code that might run a nested event loop here, so
     // we avoid running event handlers. Once we've sent the response to the
     // urgent message, it's okay to run event handlers again since the parent is
     // no longer blocked.
     MOZ_ASSERT_IF(prio > IPC::Message::PRIORITY_NORMAL, NS_IsMainThread());
     MaybeScriptBlocker scriptBlocker(this, prio > IPC::Message::PRIORITY_NORMAL);
 
     MessageChannel* dummy;
-    MessageChannel*& blockingVar = ShouldBlockScripts() ? gParentProcessBlocker : dummy;
+    MessageChannel*& blockingVar = NS_IsMainThread() ? gMainThreadBlocker : dummy;
 
     Result rv;
     if (mTimedOutMessageSeqno && mTimedOutMessagePriority >= prio) {
         // If the other side sends a message in response to one of our messages
         // that we've timed out, then we reply with an error.
         //
         // We do this because want to avoid a situation where we process an
         // incoming message from the child here while it simultaneously starts
@@ -2041,29 +2041,32 @@ MessageChannel::CancelCurrentTransaction
     mAwaitingSyncReplyPriority = 0;
 
     // We could also zero out mDispatchingSyncMessage here. However, that would
     // cause a race because mDispatchingSyncMessage is a worker-thread-only
     // field and we can be called on the I/O thread. Luckily, we can check to
     // see if mCurrentTransaction is 0 before examining DispatchSyncMessage.
 }
 
-void
+bool
 MessageChannel::CancelCurrentTransaction()
 {
     MonitorAutoLock lock(*mMonitor);
-    if (mCurrentTransaction) {
+    if (mCurrentTransaction &&
+        (DispatchingSyncMessagePriority() >= IPC::Message::PRIORITY_HIGH))
+    {
         CancelCurrentTransactionInternal();
         mLink->SendMessage(new CancelMessage());
+        return true;
     }
+    return false;
 }
 
 void
 CancelCPOWs()
 {
-    if (gParentProcessBlocker) {
+    if (gMainThreadBlocker && gMainThreadBlocker->CancelCurrentTransaction()) {
         mozilla::Telemetry::Accumulate(mozilla::Telemetry::IPC_TRANSACTION_CANCEL, true);
-        gParentProcessBlocker->CancelCurrentTransaction();
     }
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -138,17 +138,17 @@ class MessageChannel : HasResultCodes
     }
 
     void SetReplyTimeoutMs(int32_t aTimeoutMs);
 
     bool IsOnCxxStack() const {
         return !mCxxStackFrames.empty();
     }
 
-    void CancelCurrentTransaction();
+    bool CancelCurrentTransaction();
 
     /**
      * This function is used by hang annotation code to determine which IPDL
      * actor is highest in the call stack at the time of the hang. It should
      * be called from the main thread when a sync or intr message is about to
      * be sent.
      */
     int32_t GetTopmostMessageRoutingId() const;