Bug 977359 Part 2: Test case for the deadlock in the Nuwa process. r=gal

This commit is contained in:
Cervantes Yu 2014-04-15 21:26:30 +08:00
Родитель 9d2f059e24
Коммит 878e346c04
3 изменённых файлов: 119 добавлений и 0 удалений

Просмотреть файл

@ -1,3 +1,5 @@
[test_NuwaProcessCreation.html]
run-if = toolkit == 'gonk'
[test_NuwaProcessDeadlock.html]
run-if = toolkit == 'gonk'
[test_child_docshell.html]

Просмотреть файл

@ -0,0 +1,101 @@
<!DOCTYPE HTML>
<html>
<!--
Test if Nuwa process created successfully.
-->
<head>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
"use strict";
SimpleTest.waitForExplicitFinish();
function TestLoader() {}
TestLoader.prototype = {
_waitingTask: 0,
onTestReady: null,
unlockTestReady: function() {
this._waitingTask--;
this._maybeLoadTest();
},
lockTestReady: function() {
this._waitingTask++;
},
_maybeLoadTest: function() {
if (this._waitingTask == 0) {
this.onTestReady();
}
}
}
var testLoader = new TestLoader();
testLoader.lockTestReady();
window.addEventListener('load', function() {
testLoader.unlockTestReady();
});
function setPref(pref, value) {
testLoader.lockTestReady();
if (value !== undefined && value !== null) {
SpecialPowers.pushPrefEnv({'set': [[pref, value]]}, function() { testLoader.unlockTestReady(); });
} else {
SpecialPowers.pushPrefEnv({'clear': [[pref]]}, function() { testLoader.unlockTestReady(); });
}
}
setPref('dom.ipc.processPriorityManager.testMode', true);
setPref('dom.ipc.processPriorityManager.enabled', true);
setPref('dom.ipc.processPriorityManager.backgroundLRUPoolLevels', 2);
setPref('dom.ipc.processPrelaunch.testMode', true); // For testing deadlock.
function runTest()
{
// Shutdown preallocated process.
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', false);
let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(SpecialPowers.Ci.nsISyncMessageSender);
let seenNuwaReady = false;
let msgHandler = {
receiveMessage: function receiveMessage(msg) {
msg = SpecialPowers.wrap(msg);
if (msg.name == 'TEST-ONLY:nuwa-ready') {
ok(true, "Got nuwa-ready");
is(seenNuwaReady, false, "Already received nuwa ready");
seenNuwaReady = true;
} else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') {
ok(true, "Got nuwa-add-new-process");
is(seenNuwaReady, true, "Receive nuwa-add-new-process before nuwa-ready");
testEnd();
}
}
};
let timeout = setTimeout(function() {
ok(false, "Nuwa process is not launched");
testEnd();
}, 90000);
function testEnd() {
cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.removeMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
clearTimeout(timeout);
setPref('dom.ipc.processPrelaunch.testMode', false);
SimpleTest.finish();
}
cpmm.addMessageListener("TEST-ONLY:nuwa-ready", msgHandler);
cpmm.addMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler);
// Setting this pref to true should cause us to prelaunch a process.
SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true);
}
testLoader.onTestReady = runTest;
</script>
</body>
</html>

Просмотреть файл

@ -10,6 +10,11 @@
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "mozilla/ipc/ProtocolUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#include "mozilla/Preferences.h"
#endif
#include "nsDebug.h"
#include "nsISupportsImpl.h"
#include "nsXULAppAPI.h"
@ -124,6 +129,17 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid
NewRunnableMethod(this, &ProcessLink::OnTakeConnectedChannel));
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess() &&
Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) {
// The pref value is turned on in a deadlock test against the Nuwa
// process. The sleep here makes it easy to trigger the deadlock
// that an IPC channel is still opening but the worker loop is
// already frozen.
sleep(5);
}
#endif
// Should not wait here if something goes wrong with the channel.
while (!mChan->Connected() && mChan->mChannelState != ChannelError) {
mChan->mMonitor->Wait();