From 350b7f0b05442547ee01c80aa3fec64a8294ee82 Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Fri, 26 Feb 2016 17:32:28 +0100 Subject: [PATCH] Bug 1241841 - Clear the worker's debugger event queue before destroying its context;r=khuey --- dom/workers/RuntimeService.cpp | 7 +++++++ dom/workers/WorkerPrivate.cpp | 11 +++++++++++ dom/workers/WorkerPrivate.h | 3 +++ 3 files changed, 21 insertions(+) diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index b7a906355468..c971913e48e8 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -2676,6 +2676,13 @@ WorkerThreadPrimaryRunnable::Run() #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); diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 8c90df9036a5..1ecd30db1ca9 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -5020,6 +5020,17 @@ WorkerPrivate::ClearMainEventQueue(WorkerRanOrNot aRanOrNot) 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 { diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 30f553957db8..3064dfb7231b 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -1298,6 +1298,9 @@ public: void ClearMainEventQueue(WorkerRanOrNot aRanOrNot); + void + ClearDebuggerEventQueue(); + void OnProcessNextEvent();