diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp index b58a05554f96..15da1aa6fb0b 100644 --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -793,15 +793,25 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg) } void -MessageChannel::ProcessPendingRequests() +MessageChannel::ProcessPendingRequests(int transaction, int prio) { + IPC_LOG("ProcessPendingRequests"); + // Loop until there aren't any more priority messages to process. for (;;) { mozilla::Vector toProcess; for (MessageQueue::iterator it = mPending.begin(); it != mPending.end(); ) { Message &msg = *it; - if (!ShouldDeferMessage(msg)) { + + bool defer = ShouldDeferMessage(msg); + + // Only log the interesting messages. + if (msg.is_sync() || msg.priority() == IPC::Message::PRIORITY_URGENT) { + IPC_LOG("ShouldDeferMessage(seqno=%d) = %d", msg.seqno(), defer); + } + + if (!defer) { if (!toProcess.append(Move(msg))) MOZ_CRASH(); it = mPending.erase(it); @@ -815,8 +825,18 @@ MessageChannel::ProcessPendingRequests() // 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); + + // If we canceled during ProcessPendingRequest, then we need to leave + // immediately because the results of ShouldDeferMessage will be + // operating with weird state (as if no Send is in progress). That could + // cause even normal priority sync messages to be processed (but not + // normal priority async messages), which would break message ordering. + if (WasTransactionCanceled(transaction, prio)) { + return; + } } } @@ -939,8 +959,11 @@ MessageChannel::Send(Message* aMsg, Message* aReply) int32_t transaction = mCurrentTransaction; msg->set_transaction_id(transaction); - ProcessPendingRequests(); + IPC_LOG("Send seqno=%d, xid=%d", seqno, transaction); + + ProcessPendingRequests(transaction, prio); if (WasTransactionCanceled(transaction, prio)) { + IPC_LOG("Other side canceled seqno=%d, xid=%d", seqno, transaction); return false; } @@ -948,23 +971,27 @@ MessageChannel::Send(Message* aMsg, Message* aReply) mLink->SendMessage(msg.forget()); while (true) { - ProcessPendingRequests(); + ProcessPendingRequests(transaction, prio); if (WasTransactionCanceled(transaction, prio)) { + IPC_LOG("Other side canceled seqno=%d, xid=%d", seqno, transaction); return false; } // See if we've received a reply. if (mRecvdErrors) { + IPC_LOG("Error: seqno=%d, xid=%d", seqno, transaction); mRecvdErrors--; return false; } if (mRecvd) { + IPC_LOG("Got reply: seqno=%d, xid=%d", seqno, transaction); break; } MOZ_ASSERT(!mTimedOutMessageSeqno); + MOZ_ASSERT(mCurrentTransaction == transaction); bool maybeTimedOut = !WaitForSyncNotify(handleWindowsMessages); if (!Connected()) { diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h index 92476722bbc7..72c25e12eae0 100644 --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -250,7 +250,7 @@ class MessageChannel : HasResultCodes bool InterruptEventOccurred(); bool HasPendingEvents(); - void ProcessPendingRequests(); + void ProcessPendingRequests(int transaction, int prio); bool ProcessPendingRequest(const Message &aUrgent); void MaybeUndeferIncall();