Bug 1104964 - Handle ShutdownPoolsEvent race. r=cpearce, a=sledru
authorBobby Holley <bobbyholley@gmail.com>
Mon, 01 Dec 2014 21:51:02 -0800
changeset 234331 c755ca7a6484141113cfc9aacf181782b13f51b6
parent 234330 5d0d448d42bd1b07eeabc494df8be368af5c6463
child 234332 78b691bfdee36ed06fb3717e176ea8f0f1c30fac
push id7365
push userrgiles@mozilla.com
push dateMon, 15 Dec 2014 22:42:22 +0000
treeherdermozilla-aurora@874ce9bce91a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, sledru
bugs1104964
milestone36.0a2
Bug 1104964 - Handle ShutdownPoolsEvent race. r=cpearce, a=sledru
dom/media/SharedThreadPool.cpp
--- a/dom/media/SharedThreadPool.cpp
+++ b/dom/media/SharedThreadPool.cpp
@@ -49,18 +49,37 @@ public:
     DestroySharedThreadPoolHashTable();
     return NS_OK;
   }
 };
 
 static void
 DestroySharedThreadPoolHashTable()
 {
+  // We have to guard against a lot of funny business here - see the comments
+  // below. It would make more sense to just manually initialize/destroy the
+  // hashtable on startup/shutdown.
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(sMonitor && sPools);
+
+  // Check that the pool still exists to guard against this scenario:
+  // (1) sPools becomes empty, and we dispatch ShutdownPoolsEvent.
+  // (2) A new call to ::Get occurs and sPools becomes non-empty.
+  // (3) The new pool is immediately released, causing us to dispatch a second
+  //     ShutdownPoolsEvent.
+  // (4) The first ShutdownPoolsEvent runs, and deletes sPools.
+  // (5) The second ShutdownPoolsEvent runs.
+  if (!sPools) {
+    MOZ_ASSERT(!sMonitor);
+    return;
+  }
+
+  // Check that the pool is still empty to guard against this scenario:
+  // (1) sPools becomes empty, and we dispatch ShutdownPoolsEvent
+  // (2) A new call to ::Get occurs and sPools becomes non-empty.
+  // (3) The ShutdownPoolsEvent runs, with sPools now non-empty.
   if (!sPools->Count()) {
     // No more SharedThreadPool singletons. Delete the hash table.
     // Note we don't need to lock sMonitor, since we only modify the
     // hash table on the main thread, and if the hash table is empty
     // there are no external references into its contents.
     sPools = nullptr;
     sMonitor = nullptr;
   }