Bug 654926 - Hang in nsDiskCacheStreamIO::CloseOutputStream while downloading WebM video from YouTube. r=michal

This commit is contained in:
Bjarne 2011-05-19 12:45:51 +02:00
parent 0e734b3491
commit 22342d3341
3 changed files with 41 additions and 21 deletions

View File

@ -609,22 +609,34 @@ nsOutputStreamWrapper::LazyInit()
nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
rv = nsCacheService::OpenOutputStreamForEntry(cacheEntry, mode, mStartOffset,
getter_AddRefs(mOutput));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(mOutput == nsnull, "mOutput set in LazyInit");
mDescriptor->mOutput = mOutput;
nsCOMPtr<nsIOutputStream> stream;
rv = nsCacheService::OpenOutputStreamForEntry(cacheEntry, mode, mStartOffset,
getter_AddRefs(stream));
if (NS_FAILED(rv))
return rv;
nsCacheDevice* device = cacheEntry->CacheDevice();
if (!device) return NS_ERROR_NOT_AVAILABLE;
if (device) {
// the entry has been truncated to mStartOffset bytes, inform device
PRInt32 size = cacheEntry->DataSize();
rv = device->OnDataSizeChange(cacheEntry, mStartOffset - size);
if (NS_SUCCEEDED(rv))
cacheEntry->SetDataSize(mStartOffset);
} else {
rv = NS_ERROR_NOT_AVAILABLE;
}
// the entry has been truncated to mStartOffset bytes, inform the device.
PRInt32 size = cacheEntry->DataSize();
rv = device->OnDataSizeChange(cacheEntry, mStartOffset - size);
if (NS_FAILED(rv)) return rv;
cacheEntry->SetDataSize(mStartOffset);
// If anything above failed, clean up internal state and get out of here
// (see bug #654926)...
if (NS_FAILED(rv)) {
mDescriptor->InternalCleanup(stream);
return rv;
}
// ... otherwise, set members and mark initialized
mDescriptor->mOutput = mOutput = stream;
mInitialized = PR_TRUE;
return NS_OK;
}

View File

@ -77,18 +77,21 @@ public:
void CloseOutput(void)
{
if (mOutput) {
nsCOMPtr<nsIDiskCacheStreamInternal> tmp (do_QueryInterface(mOutput));
if (tmp)
tmp->CloseInternal();
else
mOutput->Close();
mOutput = nsnull;
}
InternalCleanup(mOutput);
mOutput = nsnull;
}
private:
void InternalCleanup(nsIOutputStream *stream)
{
if (stream) {
nsCOMPtr<nsIDiskCacheStreamInternal> tmp (do_QueryInterface(stream));
if (tmp)
tmp->CloseInternal();
else
stream->Close();
}
}
/*************************************************************************

View File

@ -484,8 +484,13 @@ nsDiskCacheStreamIO::Flush()
CACHE_LOG_DEBUG(("CACHE: Flush [%x doomed=%u]\n",
mBinding->mRecord.HashNumber(), mBinding->mDoomed));
if (!mBufDirty)
if (!mBufDirty) {
if (mFD) {
(void) PR_Close(mFD);
mFD = nsnull;
}
return NS_OK;
}
// write data to cache blocks, or flush mBuffer to file
nsDiskCacheMap *cacheMap = mDevice->CacheMap(); // get map reference