Backed out changeset 8470f22948e8 (bug 1312960)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sat, 29 Oct 2016 13:44:55 +0200
changeset 320027 4b390287fd434a9256a424a88f59d37cf1073362
parent 320026 4c5b55684c21a261a1f4187b290d6ac7b4d5891c
child 320028 07f30746ec45034db4a2d6da54796e6742ab7dfb
push id83310
push userarchaeopteryx@coole-files.de
push dateSat, 29 Oct 2016 11:49:17 +0000
treeherdermozilla-inbound@b38d9a1cd799 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1312960
milestone52.0a1
backs out8470f22948e80cd833132e466966d91fd435ffea
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 8470f22948e8 (bug 1312960)
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)),