Bug 1069081 - Part 1: Always cache fd in JAR cache except Windows. r=mwu

This commit is contained in:
Shian-Yow Wu 2015-07-30 16:05:57 +08:00
parent c5eba8eff5
commit da68acf71a
11 changed files with 32 additions and 162 deletions

View File

@ -2952,14 +2952,6 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
if (scheme.LowerCaseEqualsLiteral("app") ||
scheme.LowerCaseEqualsLiteral("jar")) {
mIsMappedArrayBuffer = true;
if (!XRE_IsParentProcess()) {
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(mChannel);
// For memory mapping from child process, we need to get file
// descriptor of the JAR file opened remotely on the parent proess.
// Set this to make sure that file descriptor can be obtained by
// child process.
jarChannel->EnsureChildFd();
}
}
}
}

View File

@ -8,7 +8,7 @@
interface nsIFile;
interface nsIZipEntry;
[scriptable, builtinclass, uuid(fbdfaa6b-72dc-465e-af56-572fd13f153c)]
[scriptable, builtinclass, uuid(1adea16e-aa6c-4201-8f71-e9ff0acfb52e)]
interface nsIJARChannel : nsIChannel
{
/**
@ -35,20 +35,6 @@ interface nsIJARChannel : nsIChannel
*/
readonly attribute nsIZipEntry zipEntry;
/**
* For child process, set this to make sure that a valid file descriptor of
* JAR file is always provided when calling NSPRFileDesc().
* Must be set before Open() or AsyncOpen() to be effective.
*
* Note that the file descriptor returned by NSPRFileDesc() is duplicated
* from the original, which shares its file offset with the original. If
* the file offset is modified (ex: by lseek/read/write) on one of the
* shared descriptors, the offset is also changed for the other.
* It can be safely used only with operations that take absolute offsets,
* such as mmap/pread/pwrite.
*/
void ensureChildFd();
/**
* Force the channel to skip any chack for possible interception and
* proceed immediately to the network.

View File

@ -208,7 +208,7 @@ interface nsIZipReader : nsISupports
////////////////////////////////////////////////////////////////////////////////
// nsIZipReaderCache
[scriptable, uuid(94ecd586-d405-4801-93d3-8ac7bef81bde)]
[scriptable, uuid(31179807-9fcd-46c4-befa-2ade209a394b)]
interface nsIZipReaderCache : nsISupports
{
/**
@ -245,14 +245,6 @@ interface nsIZipReaderCache : nsISupports
*/
nsIZipReader getInnerZip(in nsIFile zipFile, in AUTF8String zipEntry);
/**
* Whether to keep NSPR file descriptor for newly opened files in the cache.
* When aMustCacheFd is enabled and a file is given, the file will be flushed
* from the cache if its file descriptor was not cached.
* Note: currently not supported on Windows platform.
*/
void setMustCacheFd(in nsIFile zipFile, in bool aMustCacheFd);
/**
* Returns the cached NSPR file descriptor of the file.
* Note: currently not supported on Windows platform.

View File

@ -141,7 +141,7 @@ nsJAR::Open(nsIFile* zipFile)
mZip = zip;
return NS_OK;
}
return mZip->OpenArchive(zipFile, mCache ? mCache->IsMustCacheFdEnabled() : false);
return mZip->OpenArchive(zipFile);
}
NS_IMETHODIMP
@ -1047,7 +1047,6 @@ NS_IMPL_ISUPPORTS(nsZipReaderCache, nsIZipReaderCache, nsIObserver, nsISupportsW
nsZipReaderCache::nsZipReaderCache()
: mLock("nsZipReaderCache.mLock")
, mZips()
, mMustCacheFd(false)
#ifdef ZIP_CACHE_HIT_RATE
,
mZipCacheLookups(0),
@ -1202,54 +1201,6 @@ nsZipReaderCache::GetInnerZip(nsIFile* zipFile, const nsACString &entry,
return rv;
}
NS_IMETHODIMP
nsZipReaderCache::SetMustCacheFd(nsIFile* zipFile, bool aMustCacheFd)
{
#if defined(XP_WIN)
MOZ_CRASH("Not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
#else
if (!aMustCacheFd) {
return NS_OK;
}
if (!zipFile) {
return NS_ERROR_FAILURE;
}
nsresult rv;
nsAutoCString uri;
rv = zipFile->GetNativePath(uri);
if (NS_FAILED(rv)) {
return rv;
}
uri.Insert(NS_LITERAL_CSTRING("file:"), 0);
MutexAutoLock lock(mLock);
mMustCacheFd = aMustCacheFd;
nsRefPtr<nsJAR> zip;
mZips.Get(uri, getter_AddRefs(zip));
if (!zip) {
return NS_ERROR_FAILURE;
}
// Flush the file from the cache if its file descriptor was not cached.
PRFileDesc* fd = nullptr;
zip->GetNSPRFileDesc(&fd);
if (!fd) {
#ifdef ZIP_CACHE_HIT_RATE
mZipCacheFlushes++;
#endif
zip->SetZipReaderCache(nullptr);
mZips.Remove(uri);
}
return NS_OK;
#endif /* XP_WIN */
}
NS_IMETHODIMP
nsZipReaderCache::GetFd(nsIFile* zipFile, PRFileDesc** aRetVal)
{

View File

@ -196,10 +196,6 @@ public:
nsresult ReleaseZip(nsJAR* reader);
bool IsMustCacheFdEnabled() {
return mMustCacheFd;
}
typedef nsRefPtrHashtable<nsCStringHashKey, nsJAR> ZipsHashtable;
protected:
@ -209,7 +205,6 @@ protected:
mozilla::Mutex mLock;
uint32_t mCacheSize;
ZipsHashtable mZips;
bool mMustCacheFd;
#ifdef ZIP_CACHE_HIT_RATE
uint32_t mZipCacheLookups;

View File

@ -202,7 +202,6 @@ nsJARChannel::nsJARChannel()
, mIsPending(false)
, mIsUnsafe(true)
, mOpeningRemote(false)
, mEnsureChildFd(false)
, mSynthesizedStreamLength(0)
, mForceNoIntercept(false)
{
@ -386,9 +385,6 @@ nsJARChannel::LookupFile(bool aAllowAsync)
// file descriptor here.
return NS_OK;
#else
if (!mEnsureChildFd) {
return NS_OK;
}
PRFileDesc *fd = nullptr;
jarCache->GetFd(mJarFile, &fd);
if (fd) {
@ -405,13 +401,6 @@ nsJARChannel::LookupFile(bool aAllowAsync)
mOpeningRemote = true;
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
#else
if (mEnsureChildFd && jarCache) {
jarCache->SetMustCacheFd(remoteFile, true);
}
#endif
if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this)) {
// JarHandler will trigger OnRemoteFileOpen() after the first
// request for this file completes and we'll get a JAR cache
@ -1116,13 +1105,6 @@ nsJARChannel::GetZipEntry(nsIZipEntry **aZipEntry)
return reader->GetEntry(mJarEntry, aZipEntry);
}
NS_IMETHODIMP
nsJARChannel::EnsureChildFd()
{
mEnsureChildFd = true;
return NS_OK;
}
NS_IMETHODIMP
nsJARChannel::ForceNoIntercept()
{
@ -1250,23 +1232,21 @@ nsJARChannel::OnRemoteFileOpenComplete(nsresult aOpenStatus)
// Windows/OSX desktop builds skip remoting, we don't need file
// descriptor here.
#else
if (mEnsureChildFd) {
// Set file descriptor from Jar cache into remote Jar file, if it
// has not been set previously.
mozilla::AutoFDClose fd;
mJarFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd.rwget());
if (!fd) {
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
if (!jarCache) {
rv = NS_ERROR_FAILURE;
}
PRFileDesc *jar_fd = nullptr;
jarCache->GetFd(mJarFile, &jar_fd);
// If we failed to get fd here, an error rv would be returned
// by SetRemoteNSPRFileDesc(), which would then stop the
// channel by NotifyError().
rv = SetRemoteNSPRFileDesc(jar_fd);
// Set file descriptor from Jar cache into remote Jar file, if it
// has not been set previously.
mozilla::AutoFDClose fd;
mJarFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd.rwget());
if (!fd) {
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
if (!jarCache) {
rv = NS_ERROR_FAILURE;
}
PRFileDesc *jar_fd = nullptr;
jarCache->GetFd(mJarFile, &jar_fd);
// If we failed to get fd here, an error rv would be returned
// by SetRemoteNSPRFileDesc(), which would then stop the
// channel by NotifyError().
rv = SetRemoteNSPRFileDesc(jar_fd);
}
#endif
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_ALREADY_OPENED) {
@ -1324,14 +1304,8 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
#else
if (mEnsureChildFd) {
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
if (jarCache) {
jarCache->SetMustCacheFd(mJarFile, false);
}
// To deallocate file descriptor by RemoteOpenFileChild destructor.
mJarFile = nullptr;
}
// To deallocate file descriptor by RemoteOpenFileChild destructor.
mJarFile = nullptr;
#endif
return NS_OK;

View File

@ -122,7 +122,6 @@ private:
bool mIsPending;
bool mIsUnsafe;
bool mOpeningRemote;
bool mEnsureChildFd;
mozilla::net::MemoryDownloader::Data mTempMem;
nsCOMPtr<nsIInputStreamPump> mPump;

View File

@ -171,7 +171,7 @@ nsZipHandle::nsZipHandle()
NS_IMPL_ADDREF(nsZipHandle)
NS_IMPL_RELEASE(nsZipHandle)
nsresult nsZipHandle::Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret,
PRFileDesc **aFd)
{
mozilla::AutoFDClose fd;
@ -210,9 +210,7 @@ nsresult nsZipHandle::Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
*aFd = fd.forget();
}
#else
if (aMustCacheFd) {
handle->mNSPRFileDesc = fd.forget();
}
handle->mNSPRFileDesc = fd.forget();
#endif
handle->mMap = map;
handle->mFile.Init(file);
@ -267,6 +265,10 @@ nsresult nsZipHandle::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc)
}
*aNSPRFileDesc = mNSPRFileDesc;
if (!mNSPRFileDesc) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
@ -305,15 +307,15 @@ nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd)
return rv;
}
nsresult nsZipArchive::OpenArchive(nsIFile *aFile, bool aMustCacheFd)
nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
{
nsRefPtr<nsZipHandle> handle;
#if defined(XP_WIN)
mozilla::AutoFDClose fd;
nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle),
nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle),
&fd.rwget());
#else
nsresult rv = nsZipHandle::Init(aFile, aMustCacheFd, getter_AddRefs(handle));
nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle));
#endif
if (NS_FAILED(rv))
return rv;

View File

@ -121,10 +121,9 @@ public:
* Convenience function that generates nsZipHandle
*
* @param aFile The file used to access the zip
* @param aMustCacheFd Optional flag to keep the PRFileDesc in nsZipHandle
* @return status code
*/
nsresult OpenArchive(nsIFile *aFile, bool aMustCacheFd = false);
nsresult OpenArchive(nsIFile *aFile);
/**
* Test the integrity of items in this archive by running
@ -381,7 +380,7 @@ class nsZipHandle {
friend class nsZipArchive;
friend class mozilla::FileLocation;
public:
static nsresult Init(nsIFile *file, bool aMustCacheFd, nsZipHandle **ret,
static nsresult Init(nsIFile *file, nsZipHandle **ret,
PRFileDesc **aFd = nullptr);
static nsresult Init(nsZipArchive *zip, const char *entry,
nsZipHandle **ret);

View File

@ -277,20 +277,7 @@ if (inChild) {
// Drop any JAR caches
obs.notifyObservers(null, "chrome-flush-caches", null);
// Open the first channel without ensureChildFd()
var chan_first = ios.newChannel2(uri,
null,
null,
null, // aLoadingNode
Services.scriptSecurityManager.getSystemPrincipal(),
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER)
.QueryInterface(Ci.nsIJARChannel);
chan_first.asyncOpen(new Listener(function(l) {
}), null);
// Open multiple channels with ensureChildFd()
// Open multiple channels
var num = 10;
var chan = [];
for (var i = 0; i < num; i++) {
@ -303,12 +290,11 @@ if (inChild) {
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER)
.QueryInterface(Ci.nsIJARChannel);
chan[i].ensureChildFd();
chan[i].asyncOpen(new Listener(function(l) {
}), null);
}
// Open the last channel with ensureChildFd()
// Open the last channel
var chan_last = ios.newChannel2(uri,
null,
null,
@ -318,7 +304,6 @@ if (inChild) {
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER)
.QueryInterface(Ci.nsIJARChannel);
chan_last.ensureChildFd();
chan_last.asyncOpen(new Listener(function(l) {
run_next_test();
}), null);

View File

@ -158,11 +158,6 @@ NS_IMETHODIMP DummyChannel::GetZipEntry(nsIZipEntry* *aEntry)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::EnsureChildFd()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::Run()
{
nsresult rv = mListener->OnStartRequest(this, mListenerContext);