зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1048615 - Fix crash when simultaneously opening remote JAR file with mEnsureChildFd enabled. r=jduell
This commit is contained in:
Родитель
b7bbb3d630
Коммит
594bb622ac
|
@ -381,12 +381,7 @@ nsJARChannel::LookupFile()
|
||||||
PRFileDesc *fd = nullptr;
|
PRFileDesc *fd = nullptr;
|
||||||
jarCache->GetFd(mJarFile, &fd);
|
jarCache->GetFd(mJarFile, &fd);
|
||||||
if (fd) {
|
if (fd) {
|
||||||
PROsfd osfd = dup(PR_FileDesc2NativeHandle(fd));
|
return SetRemoteNSPRFileDesc(fd);
|
||||||
if (osfd == -1) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
remoteFile->SetNSPRFileDesc(PR_ImportFile(osfd));
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -394,18 +389,20 @@ nsJARChannel::LookupFile()
|
||||||
|
|
||||||
mOpeningRemote = true;
|
mOpeningRemote = true;
|
||||||
|
|
||||||
if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this) &&
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
|
||||||
!mEnsureChildFd) {
|
#else
|
||||||
|
if (mEnsureChildFd && jarCache) {
|
||||||
|
jarCache->SetMustCacheFd(remoteFile, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this)) {
|
||||||
// JarHandler will trigger OnRemoteFileOpen() after the first
|
// JarHandler will trigger OnRemoteFileOpen() after the first
|
||||||
// request for this file completes and we'll get a JAR cache
|
// request for this file completes and we'll get a JAR cache
|
||||||
// hit.
|
// hit.
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mEnsureChildFd && jarCache) {
|
|
||||||
jarCache->SetMustCacheFd(remoteFile, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open file on parent: OnRemoteFileOpenComplete called when done
|
// Open file on parent: OnRemoteFileOpenComplete called when done
|
||||||
nsCOMPtr<nsITabChild> tabChild;
|
nsCOMPtr<nsITabChild> tabChild;
|
||||||
NS_QueryNotificationCallbacks(this, tabChild);
|
NS_QueryNotificationCallbacks(this, tabChild);
|
||||||
|
@ -477,6 +474,24 @@ nsJARChannel::FireOnProgress(uint64_t aProgress)
|
||||||
uint64_t(mContentLength));
|
uint64_t(mContentLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsJARChannel::SetRemoteNSPRFileDesc(PRFileDesc *fd)
|
||||||
|
{
|
||||||
|
PROsfd osfd = dup(PR_FileDesc2NativeHandle(fd));
|
||||||
|
if (osfd == -1) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteOpenFileChild* remoteFile =
|
||||||
|
static_cast<RemoteOpenFileChild*>(mJarFile.get());
|
||||||
|
nsresult rv = remoteFile->SetNSPRFileDesc(PR_ImportFile(osfd));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
close(osfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// nsIRequest
|
// nsIRequest
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1035,7 +1050,32 @@ nsJARChannel::OnRemoteFileOpenComplete(nsresult aOpenStatus)
|
||||||
// NS_ERROR_ALREADY_OPENED here means we'll hit JAR cache in
|
// NS_ERROR_ALREADY_OPENED here means we'll hit JAR cache in
|
||||||
// OpenLocalFile().
|
// OpenLocalFile().
|
||||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_ALREADY_OPENED) {
|
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_ALREADY_OPENED) {
|
||||||
rv = OpenLocalFile();
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_ALREADY_OPENED) {
|
||||||
|
rv = OpenLocalFile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
@ -1087,6 +1127,8 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
||||||
mCallbacks = 0;
|
mCallbacks = 0;
|
||||||
mProgressSink = 0;
|
mProgressSink = 0;
|
||||||
|
|
||||||
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
|
||||||
|
#else
|
||||||
if (mEnsureChildFd) {
|
if (mEnsureChildFd) {
|
||||||
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
|
nsIZipReaderCache *jarCache = gJarHandler->JarCache();
|
||||||
if (jarCache) {
|
if (jarCache) {
|
||||||
|
@ -1095,6 +1137,7 @@ nsJARChannel::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status)
|
||||||
// To deallocate file descriptor by RemoteOpenFileChild destructor.
|
// To deallocate file descriptor by RemoteOpenFileChild destructor.
|
||||||
mJarFile = nullptr;
|
mJarFile = nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ private:
|
||||||
nsresult LookupFile();
|
nsresult LookupFile();
|
||||||
nsresult OpenLocalFile();
|
nsresult OpenLocalFile();
|
||||||
void NotifyError(nsresult aError);
|
void NotifyError(nsresult aError);
|
||||||
|
|
||||||
void FireOnProgress(uint64_t aProgress);
|
void FireOnProgress(uint64_t aProgress);
|
||||||
|
nsresult SetRemoteNSPRFileDesc(PRFileDesc *fd);
|
||||||
|
|
||||||
#if defined(PR_LOGGING)
|
#if defined(PR_LOGGING)
|
||||||
nsCString mSpec;
|
nsCString mSpec;
|
||||||
|
|
|
@ -58,8 +58,9 @@ Listener.prototype = {
|
||||||
onStartRequest: function(request, ctx) {
|
onStartRequest: function(request, ctx) {
|
||||||
this.gotStartRequest = true;
|
this.gotStartRequest = true;
|
||||||
},
|
},
|
||||||
onStopRequest: function(request, ctx) {
|
onStopRequest: function(request, ctx, status) {
|
||||||
this.gotStopRequest = true;
|
this.gotStopRequest = true;
|
||||||
|
do_check_eq(status, 0);
|
||||||
if (this._callback) {
|
if (this._callback) {
|
||||||
this._callback.call(null, this);
|
this._callback.call(null, this);
|
||||||
}
|
}
|
||||||
|
@ -213,4 +214,41 @@ if (!inChild) {
|
||||||
|
|
||||||
} // if !inChild
|
} // if !inChild
|
||||||
|
|
||||||
|
if (inChild) {
|
||||||
|
/**
|
||||||
|
* Multiple simultaneous opening test for bug 1048615
|
||||||
|
*/
|
||||||
|
add_test(function testSimultaneous() {
|
||||||
|
var uri = jarBase + "/inner1.zip";
|
||||||
|
|
||||||
|
// Drop any JAR caches
|
||||||
|
obs.notifyObservers(null, "chrome-flush-caches", null);
|
||||||
|
|
||||||
|
// Open the first channel without ensureChildFd()
|
||||||
|
var chan_first = ios.newChannel(uri, null, null)
|
||||||
|
.QueryInterface(Ci.nsIJARChannel);
|
||||||
|
chan_first.asyncOpen(new Listener(function(l) {
|
||||||
|
}), null);
|
||||||
|
|
||||||
|
// Open multiple channels with ensureChildFd()
|
||||||
|
var num = 10;
|
||||||
|
var chan = [];
|
||||||
|
for (var i = 0; i < num; i++) {
|
||||||
|
chan[i] = ios.newChannel(uri, null, null)
|
||||||
|
.QueryInterface(Ci.nsIJARChannel);
|
||||||
|
chan[i].ensureChildFd();
|
||||||
|
chan[i].asyncOpen(new Listener(function(l) {
|
||||||
|
}), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the last channel with ensureChildFd()
|
||||||
|
var chan_last = ios.newChannel(uri, null, null)
|
||||||
|
.QueryInterface(Ci.nsIJARChannel);
|
||||||
|
chan_last.ensureChildFd();
|
||||||
|
chan_last.asyncOpen(new Listener(function(l) {
|
||||||
|
run_next_test();
|
||||||
|
}), null);
|
||||||
|
});
|
||||||
|
} // if inChild
|
||||||
|
|
||||||
function run_test() run_next_test();
|
function run_test() run_next_test();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче