mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 1349746 - Ensure we close media cache's temporary file if the cache shuts down while we're waiting for the FD to arrive. r=jwwang
MozReview-Commit-ID: HNXt3pYb1Iv --HG-- extra : rebase_source : 5dccbbb4bf37bf31da145d70abab7373871a1413
This commit is contained in:
parent
8e0f8ac9e7
commit
a11f81c232
@ -27,7 +27,6 @@ FileBlockCache::SetCacheFile(PRFileDesc* aFD)
|
||||
|
||||
if (!aFD) {
|
||||
// Failed to get a temporary file. Shutdown.
|
||||
mInitPromise->Reject(NS_ERROR_FAILURE, __func__);
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
@ -35,7 +34,20 @@ FileBlockCache::SetCacheFile(PRFileDesc* aFD)
|
||||
MonitorAutoLock lock(mFileMonitor);
|
||||
mFD = aFD;
|
||||
}
|
||||
mInitPromise->Resolve(true, __func__);
|
||||
{
|
||||
MonitorAutoLock lock(mDataMonitor);
|
||||
if (!mIsOpen) {
|
||||
// We've been closed while waiting for the file descriptor. Bail out.
|
||||
// Rely on the destructor to close the file descriptor.
|
||||
return;
|
||||
}
|
||||
mInitialized = true;
|
||||
if (mIsWriteScheduled) {
|
||||
// A write was scheduled while waiting for FD. We need to dispatch a
|
||||
// task to service the request.
|
||||
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -53,14 +65,12 @@ FileBlockCache::Init()
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
mAbstractThread = AbstractThread::CreateXPCOMThreadWrapper(mThread, false);
|
||||
mIsOpen = true;
|
||||
|
||||
mInitPromise = new GenericPromise::Private(__func__);
|
||||
if (XRE_IsParentProcess()) {
|
||||
rv = NS_OpenAnonymousTemporaryFile(&mFD);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mInitPromise->Resolve(true, __func__);
|
||||
mInitialized = true;
|
||||
}
|
||||
} else {
|
||||
// We must request a temporary file descriptor from the parent process.
|
||||
@ -111,11 +121,13 @@ void FileBlockCache::Close()
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
MonitorAutoLock mon(mDataMonitor);
|
||||
if (!mIsOpen) {
|
||||
return;
|
||||
}
|
||||
mIsOpen = false;
|
||||
if (!mThread) {
|
||||
return;
|
||||
}
|
||||
mAbstractThread = nullptr;
|
||||
// We must shut down the thread in another runnable. This is called
|
||||
// while we're shutting down the media cache, and nsIThread::Shutdown()
|
||||
// can cause events to run before it completes, which could end up
|
||||
@ -173,14 +185,12 @@ void FileBlockCache::EnsureWriteScheduled()
|
||||
return;
|
||||
}
|
||||
mIsWriteScheduled = true;
|
||||
|
||||
RefPtr<FileBlockCache> self = this;
|
||||
mInitPromise->Then(mAbstractThread,
|
||||
__func__,
|
||||
[self](bool aValue) { self->Run(); },
|
||||
[self](nsresult rv) {}
|
||||
// Failure handled by EnsureInitialized.
|
||||
);
|
||||
if (!mInitialized) {
|
||||
// We're still waiting on a file descriptor. When it arrives,
|
||||
// the write will be scheduled.
|
||||
return;
|
||||
}
|
||||
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult FileBlockCache::Seek(int64_t aOffset)
|
||||
|
@ -163,12 +163,6 @@ private:
|
||||
// has been dispatched to preform the IO.
|
||||
// mDataMonitor must be owned while calling this.
|
||||
void EnsureWriteScheduled();
|
||||
// Promise that tracks the request for an anonymous temporary file for the
|
||||
// cache to store data into. The file descriptor must be requested from the
|
||||
// parent process when the cache is initialized. While this promise is
|
||||
// outstanding, the FileBlockCache buffers blocks in memory, and reads
|
||||
// against the cache are serviced from the in-memory buffers.
|
||||
RefPtr<GenericPromise::Private> mInitPromise;
|
||||
|
||||
// Array of block changes to made. If mBlockChanges[offset/BLOCK_SIZE] == nullptr,
|
||||
// then the block has no pending changes to be written, but if
|
||||
@ -180,15 +174,17 @@ private:
|
||||
// created upon open, and shutdown (asynchronously) upon close (on the
|
||||
// main thread).
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
// Wrapper for mThread.
|
||||
RefPtr<AbstractThread> mAbstractThread;
|
||||
// Queue of pending block indexes that need to be written or moved.
|
||||
std::deque<int32_t> mChangeIndexList;
|
||||
// True if we've dispatched an event to commit all pending block changes
|
||||
// to file on mThread.
|
||||
bool mIsWriteScheduled;
|
||||
// True if the writer is ready to write data to file.
|
||||
// True if the writer is ready to enqueue writes.
|
||||
bool mIsOpen;
|
||||
// True if we've got a temporary file descriptor. Note: we don't use mFD
|
||||
// directly as that's synchronized via mFileMonitor and we need to make
|
||||
// decisions about whether we can write while holding mDataMonitor.
|
||||
bool mInitialized = false;
|
||||
};
|
||||
|
||||
} // End namespace mozilla.
|
||||
|
Loading…
Reference in New Issue
Block a user