Bug 614513 - Crash in nsCacheService::DeactivateEntry during Linux Talos. r=bzbarsky@mit.edu, a=blocker

This commit is contained in:
Michal Novotny 2010-12-29 03:25:14 +02:00
parent 11c0641ff9
commit 81ec8f913f
7 changed files with 99 additions and 4 deletions

View File

@ -57,6 +57,7 @@ XPIDLSRCS = \
nsICacheService.idl \
nsICacheSession.idl \
nsICacheVisitor.idl \
nsIDiskCacheStreamInternal.idl \
$(NULL)
EXPORTS = \

View File

@ -273,6 +273,7 @@ nsCacheEntry::DetachDescriptors(void)
nsCacheEntryDescriptor * nextDescriptor =
(nsCacheEntryDescriptor *)PR_NEXT_LINK(descriptor);
descriptor->CloseOutput();
descriptor->ClearCacheEntry();
PR_REMOVE_AND_INIT_LINK(descriptor);
descriptor = nextDescriptor;

View File

@ -54,7 +54,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsCacheEntryDescriptor,
nsCacheEntryDescriptor::nsCacheEntryDescriptor(nsCacheEntry * entry,
nsCacheAccessMode accessGranted)
: mCacheEntry(entry),
mAccessGranted(accessGranted)
mAccessGranted(accessGranted),
mOutput(nsnull)
{
PR_INIT_CLIST(this);
NS_ADDREF(nsCacheService::GlobalInstance()); // ensure it lives for the lifetime of the descriptor
@ -612,6 +613,8 @@ nsOutputStreamWrapper::LazyInit()
getter_AddRefs(mOutput));
if (NS_FAILED(rv)) return rv;
mDescriptor->mOutput = mOutput;
nsCacheDevice* device = cacheEntry->CacheDevice();
if (!device) return NS_ERROR_NOT_AVAILABLE;

View File

@ -46,6 +46,8 @@
#include "nsCacheEntry.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsCacheService.h"
#include "nsIDiskCacheStreamInternal.h"
/******************************************************************************
* nsCacheEntryDescriptor
@ -73,6 +75,19 @@ public:
nsCacheEntry * CacheEntry(void) { return mCacheEntry; }
void ClearCacheEntry(void) { mCacheEntry = nsnull; }
void CloseOutput(void)
{
if (mOutput) {
nsCOMPtr<nsIDiskCacheStreamInternal> tmp (do_QueryInterface(mOutput));
if (tmp)
tmp->CloseInternal();
else
mOutput->Close();
mOutput = nsnull;
}
}
private:
@ -138,6 +153,10 @@ private:
{
// XXX _HACK_ the storage stream needs this!
Close();
{
nsCacheServiceAutoLock lock;
mDescriptor->mOutput = nsnull;
}
NS_RELEASE(mDescriptor);
}
@ -154,6 +173,7 @@ private:
*/
nsCacheEntry * mCacheEntry; // we are a child of the entry
nsCacheAccessMode mAccessGranted;
nsIOutputStream * mOutput;
};

View File

@ -44,6 +44,7 @@
#include "nsDiskCacheStreams.h"
#include "nsCacheService.h"
#include "mozilla/FileUtils.h"
#include "nsIDiskCacheStreamInternal.h"
@ -196,13 +197,16 @@ nsDiskCacheInputStream::IsNonBlocking(PRBool * nonBlocking)
#pragma mark -
#pragma mark nsDiskCacheOutputStream
#endif
class nsDiskCacheOutputStream : public nsIOutputStream {
class nsDiskCacheOutputStream : public nsIOutputStream
, public nsIDiskCacheStreamInternal
{
public:
nsDiskCacheOutputStream( nsDiskCacheStreamIO * parent);
virtual ~nsDiskCacheOutputStream();
NS_DECL_ISUPPORTS
NS_DECL_NSIOUTPUTSTREAM
NS_DECL_NSIDISKCACHESTREAMINTERNAL
void ReleaseStreamIO() { NS_IF_RELEASE(mStreamIO); }
@ -212,8 +216,9 @@ private:
};
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDiskCacheOutputStream,
nsIOutputStream)
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDiskCacheOutputStream,
nsIOutputStream,
nsIDiskCacheStreamInternal)
nsDiskCacheOutputStream::nsDiskCacheOutputStream( nsDiskCacheStreamIO * parent)
: mStreamIO(parent)
@ -241,6 +246,16 @@ nsDiskCacheOutputStream::Close()
return NS_OK;
}
NS_IMETHODIMP
nsDiskCacheOutputStream::CloseInternal()
{
if (!mClosed) {
mClosed = PR_TRUE;
// tell parent streamIO we are closing
mStreamIO->CloseOutputStreamInternal(this);
}
return NS_OK;
}
NS_IMETHODIMP
nsDiskCacheOutputStream::Flush()
@ -443,6 +458,13 @@ nsresult
nsDiskCacheStreamIO::CloseOutputStream(nsDiskCacheOutputStream * outputStream)
{
nsCacheServiceAutoLock lock; // grab service lock
return CloseOutputStreamInternal(outputStream);
}
nsresult
nsDiskCacheStreamIO::CloseOutputStreamInternal(
nsDiskCacheOutputStream * outputStream)
{
nsresult rv;
if (outputStream != mOutStream) {

View File

@ -66,6 +66,7 @@ public:
nsresult GetOutputStream(PRUint32 offset, nsIOutputStream ** outputStream);
nsresult CloseOutputStream(nsDiskCacheOutputStream * outputStream);
nsresult CloseOutputStreamInternal(nsDiskCacheOutputStream * outputStream);
nsresult Write( const char * buffer,
PRUint32 count,

View File

@ -0,0 +1,47 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Michal Novotny <michal.novotny@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(61ff88f7-516e-4924-93af-42e7c412d18b)]
interface nsIDiskCacheStreamInternal : nsISupports
{
/**
* We use this method internally to close nsDiskCacheOutputStream under
* the cache service lock.
*/
void closeInternal();
};