Bug 1279498 - Force WorkerPrivate->SetThread(nullptr) using a RAII, r=khuey
authorAndrea Marchesini <amarchesini@mozilla.com>
Mon, 18 Jul 2016 11:46:36 +0200
changeset 330646 2026686ebec18d7cbcb9a495926c06d7abab5d7d
parent 330457 317caf83210fb756304a5fcead0e6c824557466b
child 330647 4ab76338931e0e3f80c43f1922cb4670e5322f13
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1279498
milestone50.0a1
Bug 1279498 - Force WorkerPrivate->SetThread(nullptr) using a RAII, r=khuey
dom/workers/RuntimeService.cpp
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -2520,17 +2520,47 @@ WorkerThreadPrimaryRunnable::Run()
   // Note: SynchronouslyCreateForCurrentThread() must be called prior to
   //       mWorkerPrivate->SetThread() in order to avoid accidentally consuming
   //       worker messages here.
   if (NS_WARN_IF(!BackgroundChild::SynchronouslyCreateForCurrentThread())) {
     // XXX need to fire an error at parent.
     return NS_ERROR_UNEXPECTED;
   }
 
-  mWorkerPrivate->SetThread(mThread);
+  class MOZ_STACK_CLASS SetThreadHelper final
+  {
+    // Raw pointer: this class is on the stack.
+    WorkerPrivate* mWorkerPrivate;
+
+  public:
+    SetThreadHelper(WorkerPrivate* aWorkerPrivate, WorkerThread* aThread)
+      : mWorkerPrivate(aWorkerPrivate)
+    {
+      MOZ_ASSERT(aWorkerPrivate);
+      MOZ_ASSERT(aThread);
+
+      mWorkerPrivate->SetThread(aThread);
+    }
+
+    ~SetThreadHelper()
+    {
+      if (mWorkerPrivate) {
+        mWorkerPrivate->SetThread(nullptr);
+      }
+    }
+
+    void Nullify()
+    {
+      MOZ_ASSERT(mWorkerPrivate);
+      mWorkerPrivate->SetThread(nullptr);
+      mWorkerPrivate = nullptr;
+    }
+  };
+
+  SetThreadHelper threadHelper(mWorkerPrivate, mThread);
 
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   {
     nsCycleCollector_startup();
 
     WorkerJSRuntime runtime(mWorkerPrivate);
     nsresult rv = runtime.Initialize(mParentRuntime);
@@ -2590,17 +2620,17 @@ WorkerThreadPrimaryRunnable::Run()
     // cleanup.
     mWorkerPrivate->ClearMainEventQueue(WorkerPrivate::WorkerRan);
 
     // Now WorkerJSRuntime goes out of scope and its destructor will shut
     // down the cycle collector. This breaks any remaining cycles and collects
     // any remaining C++ objects.
   }
 
-  mWorkerPrivate->SetThread(nullptr);
+  threadHelper.Nullify();
 
   mWorkerPrivate->ScheduleDeletion(WorkerPrivate::WorkerRan);
 
   // It is no longer safe to touch mWorkerPrivate.
   mWorkerPrivate = nullptr;
 
   // Now recycle this thread.
   nsCOMPtr<nsIThread> mainThread = do_GetMainThread();