Bug 1241841 - Clear the worker's debugger event queue before destroying its context;r=khuey
authorEddy Bruel <ejpbruel@mozilla.com>
Fri, 26 Feb 2016 17:32:28 +0100
changeset 322169 2f513fdef55943e338931c9ef2a0c46f4f9cbef9
parent 322168 b0b0257a6cbe7bc4328440bcfa9b843324b17550
child 322170 a93848ae81dda184b7583759dde71ce653f25d93
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1241841
milestone47.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 1241841 - Clear the worker's debugger event queue before destroying its context;r=khuey
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2671,16 +2671,23 @@ WorkerThreadPrimaryRunnable::Run()
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
       if (stack) {
         stack->sampleRuntime(nullptr);
       }
 #endif
     }
 
+    // There may still be runnables on the debugger event queue that hold a
+    // strong reference to the debugger global scope. These runnables are not
+    // visible to the cycle collector, so we need to make sure to clear the
+    // debugger event queue before we try to destroy the context. If we don't,
+    // the garbage collector will crash.
+    mWorkerPrivate->ClearDebuggerEventQueue();
+
     // Destroy the main context. This will unroot the main worker global and GC,
     // which should break all cycles that touch JS.
     JS_DestroyContext(cx);
 
     // Before shutting down the cycle collector we need to do one more pass
     // through the event loop to clean up any C++ objects that need deferred
     // cleanup.
     mWorkerPrivate->ClearMainEventQueue(WorkerPrivate::WorkerRan);
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5015,16 +5015,27 @@ WorkerPrivate::ClearMainEventQueue(Worke
 
     NS_ProcessPendingEvents(currentThread);
   }
 
   MOZ_ASSERT(mCancelAllPendingRunnables);
   mCancelAllPendingRunnables = false;
 }
 
+void
+WorkerPrivate::ClearDebuggerEventQueue()
+{
+  while (!mDebuggerQueue.IsEmpty()) {
+    WorkerRunnable* runnable;
+    mDebuggerQueue.Pop(runnable);
+    // It should be ok to simply release the runnable, without running it.
+    runnable->Release();
+  }
+}
+
 uint32_t
 WorkerPrivate::RemainingRunTimeMS() const
 {
   if (mKillTime.IsNull()) {
     return UINT32_MAX;
   }
   TimeDuration runtime = mKillTime - TimeStamp::Now();
   double ms = runtime > TimeDuration(0) ? runtime.ToMilliseconds() : 0;
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1294,16 +1294,19 @@ public:
   {
     return mCancelAllPendingRunnables;
   }
 
   void
   ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
 
   void
+  ClearDebuggerEventQueue();
+
+  void
   OnProcessNextEvent();
 
   void
   AfterProcessNextEvent();
 
   void
   AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
 #ifdef DEBUG