Bug 976790 - Fix assertion failure, r=mrbkap.
authorBen Turner <bent.mozilla@gmail.com>
Wed, 26 Feb 2014 15:53:43 -0800
changeset 170881 3070f00e7833006dfaf5a18708becc43c1708ab8
parent 170880 1cec924f373467fa6ae86d0177ba74678bb91090
child 170882 d5f53cea0e183f54c467e81c75383a1b1ae8ab9b
push id5335
push usercbook@mozilla.com
push dateThu, 27 Feb 2014 14:43:43 +0000
treeherderfx-team@fb009d10f3e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs976790
milestone30.0a1
Bug 976790 - Fix assertion failure, r=mrbkap.
ipc/glue/BackgroundImpl.cpp
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/process_util.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/ipc/ProtocolTypes.h"
 #include "BackgroundChild.h"
@@ -136,17 +137,17 @@ private:
   // background thread. It is specific to each instance of sBackgroundThread.
   static nsTArray<ParentImpl*>* sLiveActorsForBackgroundThread;
 
   // This is only modified on the main thread.
   static StaticRefPtr<nsITimer> sShutdownTimer;
 
   // This exists so that that [Assert]IsOnBackgroundThread() can continue to
   // work during shutdown.
-  static PRThread* sBackgroundPRThread;
+  static Atomic<PRThread*> sBackgroundPRThread;
 
   // This is only modified on the main thread. It is null if the thread does not
   // exist or is shutting down.
   static MessageLoop* sBackgroundThreadMessageLoop;
 
   // This is only modified on the main thread. It maintains a count of live
   // actors so that the background thread can be shut down when it is no longer
   // needed.
@@ -792,17 +793,17 @@ const ParentImpl::ProcessHandle ParentIm
 #endif
 
 StaticRefPtr<nsIThread> ParentImpl::sBackgroundThread;
 
 nsTArray<ParentImpl*>* ParentImpl::sLiveActorsForBackgroundThread;
 
 StaticRefPtr<nsITimer> ParentImpl::sShutdownTimer;
 
-PRThread* ParentImpl::sBackgroundPRThread = nullptr;
+Atomic<PRThread*> ParentImpl::sBackgroundPRThread;
 
 MessageLoop* ParentImpl::sBackgroundThreadMessageLoop = nullptr;
 
 uint64_t ParentImpl::sLiveActorCount = 0;
 
 bool ParentImpl::sShutdownObserverRegistered = false;
 
 bool ParentImpl::sShutdownHasStarted = false;
@@ -1244,27 +1245,27 @@ ParentImpl::RequestMessageLoopRunnable::
     return NS_OK;
   }
 
   char stackBaseGuess;
   profiler_register_thread("IPDL Background", &stackBaseGuess);
 
 #ifdef DEBUG
   {
-    PRThread* currentPRThread = PR_GetCurrentThread();
-    MOZ_ASSERT(currentPRThread);
-    MOZ_ASSERT_IF(sBackgroundPRThread, currentPRThread != sBackgroundPRThread);
-
     bool correctThread;
     MOZ_ASSERT(NS_SUCCEEDED(mTargetThread->IsOnCurrentThread(&correctThread)));
     MOZ_ASSERT(correctThread);
   }
 #endif
 
-  sBackgroundPRThread = PR_GetCurrentThread();
+  DebugOnly<PRThread*> oldBackgroundThread =
+    sBackgroundPRThread.exchange(PR_GetCurrentThread());
+
+  MOZ_ASSERT_IF(oldBackgroundThread,
+                PR_GetCurrentThread() != oldBackgroundThread);
 
   MOZ_ASSERT(!mMessageLoop);
 
   mMessageLoop = MessageLoop::current();
   MOZ_ASSERT(mMessageLoop);
 
   if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
     NS_WARNING("Failed to dispatch RequestMessageLoopRunnable to main thread!");
@@ -1276,17 +1277,21 @@ ParentImpl::RequestMessageLoopRunnable::
 
 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ShutdownBackgroundThreadRunnable,
                              nsRunnable)
 
 NS_IMETHODIMP
 ParentImpl::ShutdownBackgroundThreadRunnable::Run()
 {
   AssertIsInMainProcess();
-  AssertIsOnBackgroundThread();
+
+  // It is possible that another background thread was created while this thread
+  // was shutting down. In that case we can't assert anything about
+  // sBackgroundPRThread and we should not modify it here.
+  sBackgroundPRThread.compareExchange(PR_GetCurrentThread(), nullptr);
 
   profiler_unregister_thread();
 
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(ParentImpl::ForceCloseBackgroundActorsRunnable,
                              nsRunnable)