Backed out 2 changesets (bug 1305836) for causing the failure rate of browser_bug880101.js to explode

Backed out changeset 578a4588fb7c (bug 1305836)
Backed out changeset 89a22098629e (bug 1305836)
This commit is contained in:
Phil Ringnalda 2016-09-29 21:19:55 -07:00
parent 1a0d74d8ae
commit 0c8caac0ab
5 changed files with 191 additions and 12 deletions

View File

@ -9,4 +9,5 @@
<script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript" src="chrome://mochikit/content/mochitest-e10s-utils.js"/>
<script type="application/javascript" src="chrome://mochikit/content/browser-test.js"/>
<script type="application/javascript" src="chrome://mochikit/content/cc-analyzer.js"/>
</overlay>

View File

@ -129,6 +129,8 @@ function Tester(aTests, structuredLogger, aCallback) {
this.structuredLogger = structuredLogger;
this.tests = aTests;
this.callback = aCallback;
this.openedWindows = {};
this.openedURLs = {};
this._scriptLoader = Services.scriptloader;
this.EventUtils = {};
@ -213,6 +215,7 @@ Tester.prototype = {
checker: null,
currentTestIndex: -1,
lastStartTime: null,
openedWindows: null,
lastAssertionCount: 0,
failuresFromInitialWindowState: 0,
@ -245,6 +248,8 @@ Tester.prototype = {
this.structuredLogger.info("*** Start BrowserChrome Test Results ***");
Services.console.registerListener(this);
Services.obs.addObserver(this, "chrome-document-global-created", false);
Services.obs.addObserver(this, "content-document-global-created", false);
this._globalProperties = Object.keys(window);
this._globalPropertyWhitelist = [
"navigator", "constructor", "top",
@ -365,6 +370,8 @@ Tester.prototype = {
else{
TabDestroyObserver.destroy();
Services.console.unregisterListener(this);
Services.obs.removeObserver(this, "chrome-document-global-created");
Services.obs.removeObserver(this, "content-document-global-created");
this.Promise.Debugging.clearUncaughtErrorObservers();
this._treatUncaughtRejectionsAsFailures = false;
@ -393,6 +400,7 @@ Tester.prototype = {
this.callback(this.tests);
this.callback = null;
this.tests = null;
this.openedWindows = null;
}
},
@ -402,7 +410,30 @@ Tester.prototype = {
this.repeat = 0;
},
observe: function Tester_onConsoleMessage(aConsoleMessage) {
observe: function Tester_observe(aSubject, aTopic, aData) {
if (!aTopic) {
this.onConsoleMessage(aSubject);
} else if (this.currentTest) {
this.onDocumentCreated(aSubject);
}
},
onDocumentCreated: function Tester_onDocumentCreated(aWindow) {
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let outerID = utils.outerWindowID;
let innerID = utils.currentInnerWindowID;
if (!(outerID in this.openedWindows)) {
this.openedWindows[outerID] = this.currentTest;
}
this.openedWindows[innerID] = this.currentTest;
let url = aWindow.location.href || "about:blank";
this.openedURLs[outerID] = this.openedURLs[innerID] = url;
},
onConsoleMessage: function Tester_onConsoleMessage(aConsoleMessage) {
// Ignore empty messages.
if (!aConsoleMessage.message)
return;
@ -605,19 +636,29 @@ Tester.prototype = {
// use a shrinking GC so that the JS engine will discard JIT code and
// JIT caches more aggressively.
let shutdownCleanup = aCallback => {
let checkForLeakedGlobalWindows = aCallback => {
Cu.schedulePreciseShrinkingGC(() => {
// Run the GC and CC a few times to make sure that as much
// as possible is freed.
let numCycles = 3;
for (i = 0; i < numCycles; i++) {
Cu.forceGC();
Cu.forceCC();
}
aCallback();
let analyzer = new CCAnalyzer();
analyzer.run(() => {
let results = [];
for (let obj of analyzer.find("nsGlobalWindow ")) {
let m = obj.name.match(/^nsGlobalWindow #(\d+)/);
if (m && m[1] in this.openedWindows)
results.push({ name: obj.name, url: m[1] });
}
aCallback(results);
});
});
};
let reportLeaks = aResults => {
for (let result of aResults) {
let test = this.openedWindows[result.url];
let msg = "leaked until shutdown [" + result.name +
" " + (this.openedURLs[result.url] || "NULL") + "]";
test.addResult(new testResult(false, msg, "", false));
}
};
let {AsyncShutdown} =
Cu.import("resource://gre/modules/AsyncShutdown.jsm", {});
@ -639,9 +680,17 @@ Tester.prototype = {
.getService(Ci.nsIMessageBroadcaster);
ppmm.broadcastAsyncMessage("browser-test:collect-request");
shutdownCleanup(() => {
checkForLeakedGlobalWindows(aResults => {
if (aResults.length == 0) {
this.finish();
return;
}
// After the first check, if there are reported leaked windows, sleep
// for a while, to allow off-main-thread work to complete and free up
// main-thread objects. Then check again.
setTimeout(() => {
shutdownCleanup(() => {
checkForLeakedGlobalWindows(aResults => {
reportLeaks(aResults);
this.finish();
});
}, 1000);

View File

@ -0,0 +1,127 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
function CCAnalyzer() {
}
CCAnalyzer.prototype = {
clear: function () {
this.callback = null;
this.processingCount = 0;
this.graph = {};
this.roots = [];
this.garbage = [];
this.edges = [];
this.listener = null;
},
run: function (aCallback) {
this.clear();
this.callback = aCallback;
this.listener = Cc["@mozilla.org/cycle-collector-logger;1"].
createInstance(Ci.nsICycleCollectorListener);
this.listener.disableLog = true;
this.listener.wantAfterProcessing = true;
this.runCC(3);
},
runCC: function (aCounter) {
let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
if (aCounter > 1) {
utils.garbageCollect();
setTimeout(this.runCC.bind(this, aCounter - 1), 0);
} else {
utils.garbageCollect(this.listener);
this.processLog();
}
},
processLog: function () {
// Process entire heap step by step in 5K chunks
for (let i = 0; i < 5000; i++) {
if (!this.listener.processNext(this)) {
this.callback();
this.clear();
return;
}
}
// Next chunk on timeout.
setTimeout(this.processLog.bind(this), 0);
},
noteRefCountedObject: function (aAddress, aRefCount, aObjectDescription) {
let o = this.ensureObject(aAddress);
o.address = aAddress;
o.refcount = aRefCount;
o.name = aObjectDescription;
},
noteGCedObject: function (aAddress, aMarked, aObjectDescription) {
let o = this.ensureObject(aAddress);
o.address = aAddress;
o.gcmarked = aMarked;
o.name = aObjectDescription;
},
noteEdge: function (aFromAddress, aToAddress, aEdgeName) {
let fromObject = this.ensureObject(aFromAddress);
let toObject = this.ensureObject(aToAddress);
fromObject.edges.push({name: aEdgeName, to: toObject});
toObject.owners.push({name: aEdgeName, from: fromObject});
this.edges.push({
name: aEdgeName,
from: fromObject,
to: toObject
});
},
describeRoot: function (aAddress, aKnownEdges) {
let o = this.ensureObject(aAddress);
o.root = true;
o.knownEdges = aKnownEdges;
this.roots.push(o);
},
describeGarbage: function (aAddress) {
let o = this.ensureObject(aAddress);
o.garbage = true;
this.garbage.push(o);
},
ensureObject: function (aAddress) {
if (!this.graph[aAddress])
this.graph[aAddress] = new CCObject();
return this.graph[aAddress];
},
find: function (aText) {
let result = [];
for (let address in this.graph) {
let o = this.graph[address];
if (!o.garbage && o.name.indexOf(aText) >= 0)
result.push(o);
}
return result;
}
};
function CCObject() {
this.name = "";
this.address = null;
this.refcount = 0;
this.gcmarked = false;
this.root = false;
this.garbage = false;
this.knownEdges = 0;
this.edges = [];
this.owners = [];
}

View File

@ -7,6 +7,7 @@ mochikit.jar:
content/jetpack-package-overlay.xul (jetpack-package-overlay.xul)
content/jetpack-addon-harness.js (jetpack-addon-harness.js)
content/jetpack-addon-overlay.xul (jetpack-addon-overlay.xul)
content/cc-analyzer.js (cc-analyzer.js)
content/chrome-harness.js (chrome-harness.js)
content/mochitest-e10s-utils.js (mochitest-e10s-utils.js)
content/shutdown-leaks-collector.js (shutdown-leaks-collector.js)

View File

@ -45,6 +45,7 @@ TEST_HARNESS_FILES.testing.mochitest += [
'browser-harness.xul',
'browser-test-overlay.xul',
'browser-test.js',
'cc-analyzer.js',
'chrome-harness.js',
'chunkifyTests.js',
'gen_template.pl',