Bug 851781 - Make sure that we don't reenter scriptblocker removal when we don't expect to. r=smaug, a=bajaj
authorBoris Zbarsky <bzbarsky@mit.edu>
Sat, 30 Mar 2013 00:13:52 -0400
changeset 128742 73965923ad121206d734bb4110309d0027811a38
parent 128741 95c8ca26e8bb81d48378974a94a0d3878123e248
child 128743 1f391ee6d07ed92093250c3222d3ad389d0bc064
push id3578
push userryanvm@gmail.com
push dateMon, 01 Apr 2013 14:10:55 +0000
treeherdermozilla-aurora@73965923ad12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, bajaj
bugs851781
milestone21.0a2
Bug 851781 - Make sure that we don't reenter scriptblocker removal when we don't expect to. r=smaug, a=bajaj
content/base/src/nsContentUtils.cpp
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -4975,43 +4975,57 @@ nsContentUtils::AddScriptBlocker()
   if (!sScriptBlockerCount) {
     NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
                  "Should not already have a count");
     sRunnersCountAtFirstBlocker = sBlockedScriptRunners->Length();
   }
   ++sScriptBlockerCount;
 }
 
+#ifdef DEBUG
+static bool sRemovingScriptBlockers = false;
+#endif
+
 /* static */
 void
 nsContentUtils::RemoveScriptBlocker()
 {
+  MOZ_ASSERT(!sRemovingScriptBlockers);
   NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers");
   --sScriptBlockerCount;
   if (sScriptBlockerCount) {
     return;
   }
 
   uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
   uint32_t lastBlocker = sBlockedScriptRunners->Length();
   uint32_t originalFirstBlocker = firstBlocker;
   uint32_t blockersCount = lastBlocker - firstBlocker;
   sRunnersCountAtFirstBlocker = 0;
   NS_ASSERTION(firstBlocker <= lastBlocker,
                "bad sRunnersCountAtFirstBlocker");
 
   while (firstBlocker < lastBlocker) {
-    nsCOMPtr<nsIRunnable> runnable = (*sBlockedScriptRunners)[firstBlocker];
+    nsCOMPtr<nsIRunnable> runnable;
+    runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
     ++firstBlocker;
 
+    // Calling the runnable can reenter us
     runnable->Run();
+    // So can dropping the reference to the runnable
+    runnable = nullptr;
+
     NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
                  "Bad count");
     NS_ASSERTION(!sScriptBlockerCount, "This is really bad");
   }
+#ifdef DEBUG
+  AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
+  sRemovingScriptBlockers = true;
+#endif
   sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
 }
 
 /* static */
 bool
 nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable)
 {
   if (!aRunnable) {