Bug 1496566 - avoid processing non-existent thread event queues; r=mccr8 a=lizzard
authorNathan Froyd <froydnj@mozilla.com>
Mon, 28 Jan 2019 16:12:33 -0500
changeset 515720 74d8b59043e1793036bdedb14445e3e59b6f7a51
parent 515719 e86470dd4c333f36a6f858e501f2fb7927c297f9
child 515721 5e9cc0eb20409ce001ed024890a4b6dbcbd4d02c
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8, lizzard
bugs1496566
milestone66.0
Bug 1496566 - avoid processing non-existent thread event queues; r=mccr8 a=lizzard Just because we're calling into the component manager for a service doesn't mean that we're on a thread that has an associated event loop to spin. If we are lacking such an event loop, we shouldn't try to NS_ProcessNextEvent, because that will wind up asserting that there's no event queue. Instead, just yield with the expectation that some other thread is making progress on constructing the service that we want.
xpcom/components/nsComponentManager.cpp
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -26,16 +26,17 @@
 #include "nsXPCOM.h"
 #include "nsXPCOMPrivate.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIClassInfo.h"
 #include "nsLocalFile.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "prcmon.h"
+#include "nsThreadManager.h"
 #include "nsThreadUtils.h"
 #include "prthread.h"
 #include "private/pprthred.h"
 #include "nsTArray.h"
 #include "prio.h"
 #include "ManifestParser.h"
 #include "nsNetUtil.h"
 #include "mozilla/Services.h"
@@ -1399,16 +1400,24 @@ nsComponentManagerImpl::GetServiceByCont
   while ((pendingPRThread = GetPendingServiceThread(*entry->mCIDEntry->cid))) {
     if (pendingPRThread == currentPRThread) {
       NS_ERROR("Recursive GetService!");
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     SafeMutexAutoUnlock unlockPending(mLock);
 
+    // If the current thread doesn't have an associated nsThread, then it's a
+    // thread that doesn't have an event loop to process, so we'll just try
+    // to yield to another thread in an attempt to make progress.
+    if (!nsThreadManager::get().IsNSThread()) {
+      PR_Sleep(PR_INTERVAL_NO_WAIT);
+      continue;
+    }
+
     if (!currentThread) {
       currentThread = NS_GetCurrentThread();
       MOZ_ASSERT(currentThread, "This should never be null!");
     }
 
     // This will process a single event or yield the thread if no event is
     // pending.
     if (!NS_ProcessNextEvent(currentThread, false)) {