Backed out changeset eccaf394924f (bug 1310547)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 29 Oct 2016 13:45:21 +0200
changeset 320037 d9c679129b669805d737c09c97a4768a8e6f7e6f
parent 320036 7e9f99645168e37e0f7298faebeba3e263491bbc
child 320038 ac349d1b3c10546da0193046d6ce4b7f065eb070
push id30882
push userryanvm@gmail.com
push dateSat, 29 Oct 2016 13:12:06 +0000
treeherdermozilla-central@16cdd6273c48 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1310547
milestone52.0a1
backs outeccaf394924f763f2e7797905e9259bc157f223d
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
Backed out changeset eccaf394924f (bug 1310547)
ipc/glue/BackgroundImpl.cpp
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
ipc/ipdl/ipdl/lower.py
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -1732,16 +1732,20 @@ ChildImpl::CloseForCurrentThread()
     return;
   }
 
 #ifdef DEBUG
   MOZ_ASSERT(!threadLocalInfo->mClosed);
   threadLocalInfo->mClosed = true;
 #endif
 
+  if (threadLocalInfo->mActor) {
+    threadLocalInfo->mActor->FlushPendingInterruptQueue();
+  }
+
   // Clearing the thread local will synchronously close the actor.
   DebugOnly<PRStatus> status = PR_SetThreadPrivate(sThreadLocalIndex, nullptr);
   MOZ_ASSERT(status == PR_SUCCESS);
 }
 
 // static
 BackgroundChildImpl::ThreadLocal*
 ChildImpl::GetThreadLocalForCurrentThread()
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -1779,16 +1779,38 @@ MessageChannel::MaybeUndeferIncall()
     IPC_ASSERT(0 < mRemoteStackDepthGuess, "fatal logic error");
     --mRemoteStackDepthGuess;
 
     MOZ_RELEASE_ASSERT(call.nested_level() == IPC::Message::NOT_NESTED);
     mPending.push_back(Move(call));
 }
 
 void
+MessageChannel::FlushPendingInterruptQueue()
+{
+    AssertWorkerThread();
+    mMonitor->AssertNotCurrentThreadOwns();
+
+    {
+        MonitorAutoLock lock(*mMonitor);
+
+        if (mDeferred.empty()) {
+            if (mPending.empty())
+                return;
+
+            const Message& last = mPending.back();
+            if (!last.is_interrupt() || last.is_reply())
+                return;
+        }
+    }
+
+    while (OnMaybeDequeueOne());
+}
+
+void
 MessageChannel::ExitedCxxStack()
 {
     mListener->OnExitedCxxStack();
     if (mSawInterruptOutMsg) {
         MonitorAutoLock lock(*mMonitor);
         // see long comment in OnMaybeDequeueOne()
         EnqueuePendingMessages();
         mSawInterruptOutMsg = false;
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -178,16 +178,18 @@ class MessageChannel : HasResultCodes
     /**
      * 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;
 
+    void FlushPendingInterruptQueue();
+
     // Unsound_IsClosed and Unsound_NumQueuedMessages are safe to call from any
     // thread, but they make no guarantees about whether you'll get an
     // up-to-date value; the values are written on one thread and read without
     // locking, on potentially different threads.  Thus you should only use
     // them when you don't particularly care about getting a recent value (e.g.
     // in a memory report).
     bool Unsound_IsClosed() const {
         return mLink ? mLink->Unsound_IsClosed() : true;
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -3329,19 +3329,24 @@ class _GenerateProtocolActorCode(ipdl.as
             onexitedcall.addstmt(StmtReturn(ExprCall(p.exitedCallVar())))
 
             # bool IsOnCxxStack()
             onstack = MethodDefn(
                 MethodDecl(p.onCxxStackVar().name, ret=Type.BOOL, const=1))
             onstack.addstmt(StmtReturn(ExprCall(
                 ExprSelect(p.channelVar(), '.', p.onCxxStackVar().name))))
 
+            # void ProcessIncomingRacingInterruptCall
+            processincoming = MethodDefn(
+                MethodDecl('FlushPendingInterruptQueue', ret=Type.VOID))
+            processincoming.addstmt(StmtExpr(ExprCall(ExprSelect(_actorChannel(ExprVar.THIS), '.', 'FlushPendingInterruptQueue'))))
+
             self.cls.addstmts([ onentered, onexited,
                                 onenteredcall, onexitedcall,
-                                onstack, Whitespace.NL ])
+                                onstack, processincoming, Whitespace.NL ])
 
         # OnChannelClose()
         onclose = MethodDefn(MethodDecl('OnChannelClose'))
         if ptype.isToplevel():
             onclose.addstmts([
                 StmtExpr(ExprCall(destroysubtreevar,
                                   args=[ _DestroyReason.NormalShutdown ])),
                 StmtExpr(ExprCall(deallocsubtreevar)),