Bug 1400166. P2 - Flush() should dispatch a task to clear arrays. r=gerald
authorJW Wang <jwwang@mozilla.com>
Mon, 18 Sep 2017 11:07:52 +0800
changeset 666699 45461d47b376357160c5a5768797b1a2ca03d40b
parent 666698 18b7334918f0c1bfbd1fabd691eb6e3ff4e2a1c7
child 666700 28642d47e8d26f20fbee6023d31d91fb403f8883
child 666870 93a1630a8911d78425c0acdec656d9229378131e
push id80486
push userbmo:tlin@mozilla.com
push dateTue, 19 Sep 2017 03:52:30 +0000
reviewersgerald
bugs1400166
milestone57.0a1
Bug 1400166. P2 - Flush() should dispatch a task to clear arrays. r=gerald If mBlockChanges is cleared when PerformBlockIOs() is dropping the data lock, blockIndex will become an invalid index after it acquire the data lock again. MozReview-Commit-ID: 5Cu2TgEO3F5
dom/media/FileBlockCache.cpp
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -116,20 +116,27 @@ FileBlockCache::Init()
 }
 
 void
 FileBlockCache::Flush()
 {
   LOG("Flush()");
   MutexAutoLock mon(mDataMutex);
   MOZ_ASSERT(mThread);
-  // Just discard pending changes, assume MediaCache won't read from
-  // blocks it hasn't written to.
-  mChangeIndexList.clear();
-  mBlockChanges.Clear();
+
+  // Dispatch a task so we won't clear the arrays while PerformBlockIOs() is
+  // dropping the data lock and cause InvalidArrayIndex.
+  RefPtr<FileBlockCache> self = this;
+  mThread->Dispatch(NS_NewRunnableFunction("FileBlockCache::Flush", [self]() {
+    MutexAutoLock mon(self->mDataMutex);
+    // Just discard pending changes, assume MediaCache won't read from
+    // blocks it hasn't written to.
+    self->mChangeIndexList.clear();
+    self->mBlockChanges.Clear();
+  }));
 }
 
 int32_t
 FileBlockCache::GetMaxBlocks() const
 {
   // We look up the cache size every time. This means dynamic changes
   // to the pref are applied.
   const uint32_t cacheSizeKb =
@@ -350,17 +357,17 @@ nsresult FileBlockCache::MoveBlockInFile
     return NS_ERROR_FAILURE;
   }
   return WriteBlockToFile(aDestBlockIndex, buf);
 }
 
 void
 FileBlockCache::PerformBlockIOs()
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
+  MOZ_ASSERT(mThread->IsOnCurrentThread());
   MutexAutoLock mon(mDataMutex);
   NS_ASSERTION(mIsWriteScheduled, "Should report write running or scheduled.");
 
   LOG("Run() mFD=%p mThread=%p", mFD, mThread.get());
 
   while (!mChangeIndexList.empty()) {
     if (!mThread) {
       // We've been closed, abort, discarding unwritten changes.