зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1253883 - Do not release mRWBuf until pending read/write operation finishes, r=honzab
This commit is contained in:
Родитель
d0b575b3af
Коммит
04256ec318
|
@ -250,6 +250,7 @@ CacheIndex::CacheIndex()
|
|||
, mRWBuf(nullptr)
|
||||
, mRWBufSize(0)
|
||||
, mRWBufPos(0)
|
||||
, mRWPending(false)
|
||||
, mJournalReadSuccessfully(false)
|
||||
, mFrecencyArraySorted(false)
|
||||
, mAsyncGetDiskConsumptionBlocked(false)
|
||||
|
@ -262,6 +263,7 @@ CacheIndex::CacheIndex()
|
|||
|
||||
CacheIndex::~CacheIndex()
|
||||
{
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
LOG(("CacheIndex::~CacheIndex [this=%p]", this));
|
||||
MOZ_COUNT_DTOR(CacheIndex);
|
||||
|
||||
|
@ -348,15 +350,12 @@ CacheIndex::PreShutdown()
|
|||
nsCOMPtr<nsIRunnable> event;
|
||||
event = NewRunnableMethod(index, &CacheIndex::PreShutdownInternal);
|
||||
|
||||
RefPtr<CacheIOThread> ioThread = CacheFileIOManager::IOThread();
|
||||
MOZ_ASSERT(ioThread);
|
||||
nsCOMPtr<nsIEventTarget> ioTarget = CacheFileIOManager::IOTarget();
|
||||
MOZ_ASSERT(ioTarget);
|
||||
|
||||
// Executing PreShutdownInternal() on WRITE level ensures that read/write
|
||||
// events holding pointer to mRWBuf will be executed before we release the
|
||||
// buffer by calling FinishRead()/FinishWrite() in PreShutdownInternal(), but
|
||||
// it will be executed before any queued event on INDEX level. That's OK since
|
||||
// we don't want to wait until updating of the index finishes.
|
||||
rv = ioThread->Dispatch(event, CacheIOThread::WRITE);
|
||||
// PreShutdownInternal() will be executed before any queued event on INDEX
|
||||
// level. That's OK since we don't want to wait for any operation in progess.
|
||||
rv = ioTarget->Dispatch(event, nsIEventTarget::DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("CacheIndex::PreShutdown() - Can't dispatch event");
|
||||
LOG(("CacheIndex::PreShutdown() - Can't dispatch event" ));
|
||||
|
@ -1567,7 +1566,7 @@ CacheIndex::ProcessPendingOperations()
|
|||
bool
|
||||
CacheIndex::WriteIndexToDiskIfNeeded()
|
||||
{
|
||||
if (mState != READY || mShuttingDown) {
|
||||
if (mState != READY || mShuttingDown || mRWPending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1597,6 +1596,7 @@ CacheIndex::WriteIndexToDisk()
|
|||
MOZ_ASSERT(mState == READY);
|
||||
MOZ_ASSERT(!mRWBuf);
|
||||
MOZ_ASSERT(!mRWHash);
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
ChangeState(WRITING);
|
||||
|
||||
|
@ -1637,6 +1637,7 @@ CacheIndex::WriteRecords()
|
|||
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(mState == WRITING);
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
int64_t fileOffset;
|
||||
|
||||
|
@ -1713,6 +1714,8 @@ CacheIndex::WriteRecords()
|
|||
LOG(("CacheIndex::WriteRecords() - CacheFileIOManager::Write() failed "
|
||||
"synchronously [rv=0x%08x]", rv));
|
||||
FinishWrite(false);
|
||||
} else {
|
||||
mRWPending = true;
|
||||
}
|
||||
|
||||
mRWBufPos = 0;
|
||||
|
@ -1727,6 +1730,10 @@ CacheIndex::FinishWrite(bool aSucceeded)
|
|||
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
|
||||
// If there is write operation pending we must be cancelling writing of the
|
||||
// index when shutting down or removing the whole index.
|
||||
MOZ_ASSERT(!mRWPending || (!aSucceeded && (mShuttingDown || mRemovingAll)));
|
||||
|
||||
mIndexHandle = nullptr;
|
||||
mRWHash = nullptr;
|
||||
ReleaseBuffer();
|
||||
|
@ -2059,6 +2066,7 @@ CacheIndex::StartReadingIndex()
|
|||
MOZ_ASSERT(!mDontMarkIndexClean);
|
||||
MOZ_ASSERT(!mJournalReadSuccessfully);
|
||||
MOZ_ASSERT(mIndexHandle->FileSize() >= 0);
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
int64_t entriesSize = mIndexHandle->FileSize() - sizeof(CacheIndexHeader) -
|
||||
sizeof(CacheHash::Hash32_t);
|
||||
|
@ -2081,6 +2089,8 @@ CacheIndex::StartReadingIndex()
|
|||
LOG(("CacheIndex::StartReadingIndex() - CacheFileIOManager::Read() failed "
|
||||
"synchronously [rv=0x%08x]", rv));
|
||||
FinishRead(false);
|
||||
} else {
|
||||
mRWPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2093,6 +2103,8 @@ CacheIndex::ParseRecords()
|
|||
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
uint32_t entryCnt = (mIndexHandle->FileSize() - sizeof(CacheIndexHeader) -
|
||||
sizeof(CacheHash::Hash32_t)) / sizeof(CacheIndexRecord);
|
||||
uint32_t pos = 0;
|
||||
|
@ -2209,6 +2221,8 @@ CacheIndex::ParseRecords()
|
|||
"synchronously [rv=0x%08x]", rv));
|
||||
FinishRead(false);
|
||||
return;
|
||||
} else {
|
||||
mRWPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2225,6 +2239,7 @@ CacheIndex::StartReadingJournal()
|
|||
MOZ_ASSERT(mIndexOnDiskIsValid);
|
||||
MOZ_ASSERT(mTmpJournal.Count() == 0);
|
||||
MOZ_ASSERT(mJournalHandle->FileSize() >= 0);
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
int64_t entriesSize = mJournalHandle->FileSize() -
|
||||
sizeof(CacheHash::Hash32_t);
|
||||
|
@ -2246,6 +2261,8 @@ CacheIndex::StartReadingJournal()
|
|||
LOG(("CacheIndex::StartReadingJournal() - CacheFileIOManager::Read() failed"
|
||||
" synchronously [rv=0x%08x]", rv));
|
||||
FinishRead(false);
|
||||
} else {
|
||||
mRWPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2258,6 +2275,8 @@ CacheIndex::ParseJournal()
|
|||
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
|
||||
MOZ_ASSERT(!mRWPending);
|
||||
|
||||
uint32_t entryCnt = (mJournalHandle->FileSize() -
|
||||
sizeof(CacheHash::Hash32_t)) / sizeof(CacheIndexRecord);
|
||||
|
||||
|
@ -2323,6 +2342,8 @@ CacheIndex::ParseJournal()
|
|||
"synchronously [rv=0x%08x]", rv));
|
||||
FinishRead(false);
|
||||
return;
|
||||
} else {
|
||||
mRWPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2407,6 +2428,10 @@ CacheIndex::FinishRead(bool aSucceeded)
|
|||
// -> ready
|
||||
(aSucceeded && mIndexOnDiskIsValid && mJournalReadSuccessfully));
|
||||
|
||||
// If there is read operation pending we must be cancelling reading of the
|
||||
// index when shutting down or removing the whole index.
|
||||
MOZ_ASSERT(!mRWPending || (!aSucceeded && (mShuttingDown || mRemovingAll)));
|
||||
|
||||
if (mState == SHUTDOWN) {
|
||||
RemoveFile(NS_LITERAL_CSTRING(TEMP_INDEX_NAME));
|
||||
RemoveFile(NS_LITERAL_CSTRING(JOURNAL_NAME));
|
||||
|
@ -3168,10 +3193,14 @@ CacheIndex::AllocBuffer()
|
|||
void
|
||||
CacheIndex::ReleaseBuffer()
|
||||
{
|
||||
if (!mRWBuf) {
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
|
||||
if (!mRWBuf || mRWPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(("CacheIndex::ReleaseBuffer() releasing buffer"));
|
||||
|
||||
free(mRWBuf);
|
||||
mRWBuf = nullptr;
|
||||
mRWBufSize = 0;
|
||||
|
@ -3279,13 +3308,13 @@ CacheIndex::OnFileOpenedInternal(FileOpenHelper *aOpener,
|
|||
LOG(("CacheIndex::OnFileOpenedInternal() [opener=%p, handle=%p, "
|
||||
"result=0x%08x]", aOpener, aHandle, aResult));
|
||||
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
sLock.AssertCurrentThreadOwns();
|
||||
|
||||
if (!IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(IsIndexUsable());
|
||||
|
||||
if (mState == READY && mShuttingDown) {
|
||||
return NS_OK;
|
||||
|
@ -3389,13 +3418,15 @@ CacheIndex::OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
|
|||
LOG(("CacheIndex::OnDataWritten() [handle=%p, result=0x%08x]", aHandle,
|
||||
aResult));
|
||||
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
|
||||
if (!IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(IsIndexUsable());
|
||||
MOZ_RELEASE_ASSERT(mRWPending);
|
||||
mRWPending = false;
|
||||
|
||||
if (mState == READY && mShuttingDown) {
|
||||
return NS_OK;
|
||||
|
@ -3403,11 +3434,7 @@ CacheIndex::OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
|
|||
|
||||
switch (mState) {
|
||||
case WRITING:
|
||||
if (mIndexHandle != aHandle) {
|
||||
LOG(("CacheIndex::OnDataWritten() - ignoring notification since it "
|
||||
"belongs to previously canceled operation [state=%d]", mState));
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(mIndexHandle == aHandle);
|
||||
|
||||
if (NS_FAILED(aResult)) {
|
||||
FinishWrite(false);
|
||||
|
@ -3430,6 +3457,7 @@ CacheIndex::OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
|
|||
// Writing was canceled.
|
||||
LOG(("CacheIndex::OnDataWritten() - ignoring notification since the "
|
||||
"operation was previously canceled [state=%d]", mState));
|
||||
ReleaseBuffer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3441,11 +3469,13 @@ CacheIndex::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult)
|
|||
LOG(("CacheIndex::OnDataRead() [handle=%p, result=0x%08x]", aHandle,
|
||||
aResult));
|
||||
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
|
||||
if (!IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(IsIndexUsable());
|
||||
MOZ_RELEASE_ASSERT(mRWPending);
|
||||
mRWPending = false;
|
||||
|
||||
switch (mState) {
|
||||
case READING:
|
||||
|
@ -3465,6 +3495,7 @@ CacheIndex::OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult)
|
|||
// Reading was canceled.
|
||||
LOG(("CacheIndex::OnDataRead() - ignoring notification since the "
|
||||
"operation was previously canceled [state=%d]", mState));
|
||||
ReleaseBuffer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3490,11 +3521,11 @@ CacheIndex::OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult)
|
|||
LOG(("CacheIndex::OnFileRenamed() [handle=%p, result=0x%08x]", aHandle,
|
||||
aResult));
|
||||
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||
|
||||
StaticMutexAutoLock lock(sLock);
|
||||
|
||||
if (!IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(IsIndexUsable());
|
||||
|
||||
if (mState == READY && mShuttingDown) {
|
||||
return NS_OK;
|
||||
|
|
|
@ -991,6 +991,10 @@ private:
|
|||
uint32_t mRWBufPos;
|
||||
RefPtr<CacheHash> mRWHash;
|
||||
|
||||
// True if read or write operation is pending. It is used to ensure that
|
||||
// mRWBuf is not freed until OnDataRead or OnDataWritten is called.
|
||||
bool mRWPending;
|
||||
|
||||
// Reading of journal succeeded if true.
|
||||
bool mJournalReadSuccessfully;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче