Bug 1142109 - Process incoming urgent messages before sending (r=dvander)
authorBill McCloskey <billm@mozilla.com>
Wed, 11 Mar 2015 20:32:47 -0700
changeset 264458 da4cb8b985170a06da8d73347e7ffc55a307c2b5
parent 264457 ec2acf8601871f1ead377effe381257bcc1775bb
child 264459 56267a6107055035980f4e86e1dbf33e630ea3a0
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1142109
milestone39.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 1142109 - Process incoming urgent messages before sending (r=dvander)
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
ipc/ipdl/test/cxx/TestUrgentHangs.cpp
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -702,16 +702,43 @@ MessageChannel::OnMessageReceivedFromLin
         if (!compress) {
             // If we compressed away the previous message, we'll re-use
             // its pending task.
             mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mDequeueOneTask));
         }
     }
 }
 
+void
+MessageChannel::ProcessPendingRequests()
+{
+    // Loop until there aren't any more priority messages to process.
+    for (;;) {
+        mozilla::Vector<Message> toProcess;
+
+        for (MessageQueue::iterator it = mPending.begin(); it != mPending.end(); ) {
+            Message &msg = *it;
+            if (!ShouldDeferMessage(msg)) {
+                toProcess.append(Move(msg));
+                it = mPending.erase(it);
+                continue;
+            }
+            it++;
+        }
+
+        if (toProcess.empty())
+            break;
+
+        // Processing these messages could result in more messages, so we
+        // loop around to check for more afterwards.
+        for (auto it = toProcess.begin(); it != toProcess.end(); it++)
+            ProcessPendingRequest(*it);
+    }
+}
+
 bool
 MessageChannel::Send(Message* aMsg, Message* aReply)
 {
     // See comment in DispatchSyncMessage.
     MaybeScriptBlocker scriptBlocker(this, true);
 
     // Sanity checks.
     AssertWorkerThread();
@@ -761,41 +788,22 @@ MessageChannel::Send(Message* aMsg, Mess
 
     AutoSetValue<bool> replies(mAwaitingSyncReply, true);
     AutoSetValue<int> prio(mAwaitingSyncReplyPriority, msg->priority());
     AutoEnterTransaction transact(this, seqno);
 
     int32_t transaction = mCurrentTransaction;
     msg->set_transaction_id(transaction);
 
+    ProcessPendingRequests();
+
     mLink->SendMessage(msg.forget());
 
     while (true) {
-        // Loop until there aren't any more priority messages to process.
-        for (;;) {
-            mozilla::Vector<Message> toProcess;
-
-            for (MessageQueue::iterator it = mPending.begin(); it != mPending.end(); ) {
-                Message &msg = *it;
-                if (!ShouldDeferMessage(msg)) {
-                    toProcess.append(Move(msg));
-                    it = mPending.erase(it);
-                    continue;
-                }
-                it++;
-            }
-
-            if (toProcess.empty())
-                break;
-
-            // Processing these messages could result in more messages, so we
-            // loop around to check for more afterwards.
-            for (auto it = toProcess.begin(); it != toProcess.end(); it++)
-                ProcessPendingRequest(*it);
-        }
+        ProcessPendingRequests();
 
         // See if we've received a reply.
         if (mRecvdErrors) {
             mRecvdErrors--;
             return false;
         }
 
         if (mRecvd) {
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -222,16 +222,17 @@ class MessageChannel : HasResultCodes
     void Clear();
 
     // Send OnChannelConnected notification to listeners.
     void DispatchOnChannelConnected();
 
     bool InterruptEventOccurred();
     bool HasPendingEvents();
 
+    void ProcessPendingRequests();
     bool ProcessPendingRequest(const Message &aUrgent);
 
     void MaybeUndeferIncall();
     void EnqueuePendingMessages();
 
     // Executed on the worker thread. Dequeues one pending message.
     bool OnMaybeDequeueOne();
     bool DequeueOne(Message *recvd);
--- a/ipc/ipdl/test/cxx/TestUrgentHangs.cpp
+++ b/ipc/ipdl/test/cxx/TestUrgentHangs.cpp
@@ -133,19 +133,19 @@ TestUrgentHangsChild::RecvTest3()
     return true;
 }
 
 bool
 TestUrgentHangsChild::RecvTest4()
 {
     PR_Sleep(PR_SecondsToInterval(2));
 
-    // This should fail because Test4_1 timed out and hasn't gotten a response
-    // yet.
-    if (SendTestInner())
+    // This won't fail because we should handle Test4_1 here before actually
+    // sending TestInner to the parent.
+    if (!SendTestInner())
         fail("sending TestInner");
 
     return true;
 }
 
 bool
 TestUrgentHangsChild::RecvTest4_1()
 {