Bug 784647: Ensure that Tasks and XPCOM events are dispatched with the same priority. r=bent
authorChris Jones <jones.chris.g@gmail.com>
Sat, 25 Aug 2012 01:25:08 -0700
changeset 103418 779bdf71cde512dc03ca698b7d1c715ed80bbd28
parent 103417 34081ff6b8ac8984abff8c0b0f374a8762720cb4
child 103419 8b88613cd6f895d2b87e237b86f8e458034ffc06
push id13981
push userryanvm@gmail.com
push dateSat, 25 Aug 2012 19:48:18 +0000
treeherdermozilla-inbound@779bdf71cde5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs784647
milestone17.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 784647: Ensure that Tasks and XPCOM events are dispatched with the same priority. r=bent
ipc/glue/MessagePump.cpp
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -78,19 +78,20 @@ MessagePump::Run(MessagePump::Delegate* 
 
   for (;;) {
     autoReleasePool.Recycle();
 
     bool did_work = NS_ProcessNextEvent(mThread, false) ? true : false;
     if (!keep_running_)
       break;
 
-    did_work |= aDelegate->DoWork();
-    if (!keep_running_)
-      break;
+    // NB: it is crucial *not* to directly call |aDelegate->DoWork()|
+    // here.  To ensure that MessageLoop tasks and XPCOM events have
+    // equal priority, we sensitively rely on processing exactly one
+    // Task per DoWorkRunnable XPCOM event.
 
 #ifdef MOZ_WIDGET_ANDROID
     // This processes messages in the Android Looper. Note that we only
     // get here if the normal Gecko event loop has been awoken above.
     // Bug 750713
     AndroidBridge::Bridge()->PumpMessageLoop();
 #endif
 
@@ -202,11 +203,30 @@ MessagePumpForChildProcess::Run(MessageP
     gFirstDelegate = nullptr;
 #endif
     return;
   }
 
 #ifdef DEBUG
   NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
 #endif
+
+  // We can get to this point in startup with Tasks in our loop's
+  // incoming_queue_ or pending_queue_, but without a matching
+  // DoWorkRunnable().  In MessagePump::Run() above, we sensitively
+  // depend on *not* directly calling delegate->DoWork(), because that
+  // prioritizes Tasks above XPCOM events.  However, from this point
+  // forward, any Task posted to our loop is guaranteed to have a
+  // DoWorkRunnable enqueued for it.
+  //
+  // So we just flush the pending work here and move on.
+  MessageLoop* loop = MessageLoop::current();
+  bool nestableTasksAllowed = loop->NestableTasksAllowed();
+  loop->SetNestableTasksAllowed(true);
+
+  while (aDelegate->DoWork());
+
+  loop->SetNestableTasksAllowed(nestableTasksAllowed);
+
+
   // Really run.
   mozilla::ipc::MessagePump::Run(aDelegate);
 }