Bug 1151646 - Spin the event loop one extra time to clean up all CC'd objects before worker shutdown, r=khuey.
authorBen Turner <bent.mozilla@gmail.com>
Wed, 08 Apr 2015 15:20:59 -0700
changeset 268112 736c8f8f8c9bb45f8e453a18bd490c5c2f386e9a
parent 268111 e99573cc529ced09472d48e1269db4eea50a0307
child 268113 d225c07cf67148ad12eaaaf6cc9756e3cae71da4
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1151646
milestone40.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 1151646 - Spin the event loop one extra time to clean up all CC'd objects before worker shutdown, r=khuey.
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.h
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2757,25 +2757,28 @@ WorkerThreadPrimaryRunnable::Run()
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
       if (stack) {
         stack->sampleRuntime(nullptr);
       }
 #endif
     }
 
-    // Destroy the main context.  This will unroot the main worker global and
-    // GC.  This is not the last JSContext (WorkerJSRuntime maintains an
-    // internal JSContext).
+    // 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);
+
     // Now WorkerJSRuntime goes out of scope and its destructor will shut
-    // down the cycle collector and destroy the final JSContext.  This
-    // breaks any remaining cycles and collects the C++ and JS objects
-    // participating.
+    // down the cycle collector. This breaks any remaining cycles and collects
+    // any remaining C++ objects.
   }
 
   mWorkerPrivate->SetThread(nullptr);
 
   mWorkerPrivate->ScheduleDeletion(WorkerPrivate::WorkerRan);
 
   // It is no longer safe to touch mWorkerPrivate.
   mWorkerPrivate = nullptr;
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1206,16 +1206,19 @@ public:
 
   bool
   AllPendingRunnablesShouldBeCanceled() const
   {
     return mCancelAllPendingRunnables;
   }
 
   void
+  ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
+
+  void
   OnProcessNextEvent(uint32_t aRecursionDepth);
 
   void
   AfterProcessNextEvent(uint32_t aRecursionDepth);
 
   void
   AssertValidSyncLoop(nsIEventTarget* aSyncLoopTarget)
 #ifdef DEBUG
@@ -1247,19 +1250,16 @@ public:
   RunBeforeNextEvent(nsIRunnable* aRunnable);
 
 private:
   WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent,
                 const nsAString& aScriptURL, bool aIsChromeWorker,
                 WorkerType aWorkerType, const nsACString& aSharedWorkerName,
                 WorkerLoadInfo& aLoadInfo);
 
-  void
-  ClearMainEventQueue(WorkerRanOrNot aRanOrNot);
-
   bool
   MayContinueRunning()
   {
     AssertIsOnWorkerThread();
 
     Status status;
     {
       MutexAutoLock lock(mMutex);