Bug 1400166. P2 - Flush() should dispatch a task to clear arrays.
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
--- 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.