diff --git a/browser/base/content/test/tabcrashed/browser.ini b/browser/base/content/test/tabcrashed/browser.ini index 6542f241b95b..1266fb0564f0 100644 --- a/browser/base/content/test/tabcrashed/browser.ini +++ b/browser/base/content/test/tabcrashed/browser.ini @@ -5,12 +5,6 @@ support-files = file_contains_emptyiframe.html file_iframe.html -[browser_aboutRestartRequired_basic.js] -skip-if = - !debug -[browser_aboutRestartRequired_buildid.js] -skip-if = - !debug [browser_autoSubmitRequest.js] [browser_launchFail.js] [browser_multipleCrashedTabs.js] diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired.ini b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired.ini new file mode 100644 index 000000000000..f6f2cfea93ad --- /dev/null +++ b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired.ini @@ -0,0 +1,13 @@ +[DEFAULT] +skip-if = + !debug || !e10s || !crashreporter +support-files = + head.js +prefs = + dom.ipc.processCount=1 + dom.ipc.processPrelaunch.fission.number=0 + +[browser_aboutRestartRequired_basic.js] +[browser_aboutRestartRequired_buildid_false-positive.js] +[browser_aboutRestartRequired_buildid_mismatch.js] +[browser_aboutRestartRequired_buildid_no-platform-ini.js] diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_basic.js b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_basic.js index 34b4b284edd1..d62372cbba71 100644 --- a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_basic.js +++ b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_basic.js @@ -1,6 +1,11 @@ "use strict"; -const kTimeout = 5 * 1000; +// On debug builds, crashing tabs results in much thinking, which +// slows down the test and results in intermittent test timeouts, +// so we'll pump up the expected timeout for this test. +requestLongerTimeout(5); + +SimpleTest.expectChildProcessCrash(); add_task(async function test_browser_crashed_basic_event() { info("Waiting for oop-browser-crashed event."); @@ -12,8 +17,9 @@ add_task(async function test_browser_crashed_basic_event() { "Build ID mismatch false positive count should be undefined" ); - let eventPromise = getEventPromise("oop-browser-crashed", "basic", kTimeout); - await openNewTab(true); + await forceCleanProcesses(); + let eventPromise = getEventPromise("oop-browser-crashed", "basic"); + let tab = await openNewTab(true); await eventPromise; is( @@ -21,4 +27,5 @@ add_task(async function test_browser_crashed_basic_event() { undefined, "Build ID mismatch false positive count should be undefined" ); + await closeTab(tab); }); diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid.js b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid.js deleted file mode 100644 index ff5deac703e2..000000000000 --- a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid.js +++ /dev/null @@ -1,184 +0,0 @@ -"use strict"; - -const kTimeout = 60 * 1000; - -// On debug builds, crashing tabs results in much thinking, which -// slows down the test and results in intermittent test timeouts, -// so we'll pump up the expected timeout for this test. -requestLongerTimeout(5); - -async function waitForObserver(topic) { - return new Promise(function(resolve, reject) { - info("Setting up observer for '" + topic + "'"); - let interval = undefined; - - let obs = { - observe() { - info("Observed '" + topic + "'"); - clearInterval(interval); - Services.obs.removeObserver(obs, topic); - resolve(); - }, - }; - - Services.obs.addObserver(obs, topic); - - let times = 0; - let intervalMs = 1000; - interval = setInterval(async () => { - info("Opening and closing tab '" + topic + "'"); - await openNewTab(false); - times += intervalMs; - if (times > kTimeout) { - clearInterval(interval); - reject(); - } - }, intervalMs); - }); -} - -async function forceCleanProcesses() { - const origPrefValue = SpecialPowers.getBoolPref( - "dom.ipc.processPrelaunch.enabled" - ); - info( - "forceCleanProcesses: get dom.ipc.processPrelaunch.enabled=" + origPrefValue - ); - await SpecialPowers.setBoolPref("dom.ipc.processPrelaunch.enabled", false); - info("forceCleanProcesses: set dom.ipc.processPrelaunch.enabled=false"); - await SpecialPowers.setBoolPref( - "dom.ipc.processPrelaunch.enabled", - origPrefValue - ); - info( - "forceCleanProcesses: set dom.ipc.processPrelaunch.enabled=" + origPrefValue - ); - const currPrefValue = SpecialPowers.getBoolPref( - "dom.ipc.processPrelaunch.enabled" - ); - ok(currPrefValue === origPrefValue, "processPrelaunch properly re-enabled"); -} - -add_task(async function test_browser_crashed_false_positive_event() { - info("Waiting for oop-browser-crashed event."); - - Services.telemetry.clearScalars(); - is( - getFalsePositiveTelemetry(), - undefined, - "Build ID mismatch false positive count should be undefined" - ); - - try { - setBuildidMatchDontSendEnv(); - await forceCleanProcesses(); - let eventPromise = getEventPromise( - "oop-browser-crashed", - "false-positive", - kTimeout - ); - await openNewTab(false); - await eventPromise; - } finally { - unsetBuildidMatchDontSendEnv(); - } - - is( - getFalsePositiveTelemetry(), - 1, - "Build ID mismatch false positive count should be 1" - ); -}); - -add_task(async function test_browser_restartrequired_event() { - info("Waiting for oop-browser-buildid-mismatch event."); - - Services.telemetry.clearScalars(); - is( - getFalsePositiveTelemetry(), - undefined, - "Build ID mismatch false positive count should be undefined" - ); - - let profD = Services.dirsvc.get("GreD", Ci.nsIFile); - let platformIniOrig = await IOUtils.readUTF8( - PathUtils.join(profD.path, "platform.ini") - ); - let buildID = Services.appinfo.platformBuildID; - let platformIniNew = platformIniOrig.replace(buildID, "1234"); - - await IOUtils.writeUTF8( - PathUtils.join(profD.path, "platform.ini"), - platformIniNew - ); - - try { - setBuildidMatchDontSendEnv(); - await forceCleanProcesses(); - let eventPromise = getEventPromise( - "oop-browser-buildid-mismatch", - "buildid-mismatch", - kTimeout - ); - await openNewTab(false); - - await eventPromise; - } finally { - await IOUtils.writeUTF8( - PathUtils.join(profD.path, "platform.ini"), - platformIniOrig - ); - - unsetBuildidMatchDontSendEnv(); - } - - is( - getFalsePositiveTelemetry(), - undefined, - "Build ID mismatch false positive count should be undefined" - ); -}); - -add_task(async function test_browser_crashed_no_platform_ini_event() { - info("Waiting for oop-browser-buildid-mismatch event."); - - Services.telemetry.clearScalars(); - is( - getFalsePositiveTelemetry(), - undefined, - "Build ID mismatch false positive count should be undefined" - ); - - let profD = Services.dirsvc.get("GreD", Ci.nsIFile); - let platformIniOrig = await IOUtils.readUTF8( - PathUtils.join(profD.path, "platform.ini") - ); - - await IOUtils.remove(PathUtils.join(profD.path, "platform.ini")); - - try { - setBuildidMatchDontSendEnv(); - await forceCleanProcesses(); - let eventPromise = getEventPromise( - "oop-browser-buildid-mismatch", - "no-platform-ini", - kTimeout - ); - await openNewTab(false); - - await eventPromise; - } finally { - await IOUtils.writeUTF8( - PathUtils.join(profD.path, "platform.ini"), - platformIniOrig - ); - - unsetBuildidMatchDontSendEnv(); - } - - is( - getFalsePositiveTelemetry(), - undefined, - "Build ID mismatch false positive count should be undefined" - ); -}); diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_false-positive.js b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_false-positive.js new file mode 100644 index 000000000000..15e0b5ab312f --- /dev/null +++ b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_false-positive.js @@ -0,0 +1,35 @@ +"use strict"; + +// On debug builds, crashing tabs results in much thinking, which +// slows down the test and results in intermittent test timeouts, +// so we'll pump up the expected timeout for this test. +requestLongerTimeout(2); + +SimpleTest.expectChildProcessCrash(); + +add_task(async function test_browser_crashed_false_positive_event() { + info("Waiting for oop-browser-crashed event."); + + Services.telemetry.clearScalars(); + is( + getFalsePositiveTelemetry(), + undefined, + "Build ID mismatch false positive count should be undefined" + ); + + ok(await ensureBuildID(), "System has correct platform.ini"); + setBuildidMatchDontSendEnv(); + await forceCleanProcesses(); + let eventPromise = getEventPromise("oop-browser-crashed", "false-positive"); + let tab = await openNewTab(false); + await eventPromise; + unsetBuildidMatchDontSendEnv(); + + is( + getFalsePositiveTelemetry(), + 1, + "Build ID mismatch false positive count should be 1" + ); + + await closeTab(tab); +}); diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_mismatch.js b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_mismatch.js new file mode 100644 index 000000000000..80f35db159f6 --- /dev/null +++ b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_mismatch.js @@ -0,0 +1,56 @@ +"use strict"; + +// On debug builds, crashing tabs results in much thinking, which +// slows down the test and results in intermittent test timeouts, +// so we'll pump up the expected timeout for this test. +requestLongerTimeout(2); + +SimpleTest.expectChildProcessCrash(); + +add_task(async function test_browser_restartrequired_event() { + info("Waiting for oop-browser-buildid-mismatch event."); + + Services.telemetry.clearScalars(); + is( + getFalsePositiveTelemetry(), + undefined, + "Build ID mismatch false positive count should be undefined" + ); + + ok(await ensureBuildID(), "System has correct platform.ini"); + + let profD = Services.dirsvc.get("GreD", Ci.nsIFile); + let platformIniOrig = await IOUtils.readUTF8( + PathUtils.join(profD.path, "platform.ini") + ); + let buildID = Services.appinfo.platformBuildID; + let platformIniNew = platformIniOrig.replace(buildID, "1234"); + + await IOUtils.writeUTF8( + PathUtils.join(profD.path, "platform.ini"), + platformIniNew, + { flush: true } + ); + + setBuildidMatchDontSendEnv(); + await forceCleanProcesses(); + let eventPromise = getEventPromise( + "oop-browser-buildid-mismatch", + "buildid-mismatch" + ); + let tab = await openNewTab(false); + await eventPromise; + await IOUtils.writeUTF8( + PathUtils.join(profD.path, "platform.ini"), + platformIniOrig, + { flush: true } + ); + unsetBuildidMatchDontSendEnv(); + + is( + getFalsePositiveTelemetry(), + undefined, + "Build ID mismatch false positive count should be undefined" + ); + await closeTab(tab); +}); diff --git a/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_no-platform-ini.js b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_no-platform-ini.js new file mode 100644 index 000000000000..232c79b02e83 --- /dev/null +++ b/browser/base/content/test/tabcrashed/browser_aboutRestartRequired_buildid_no-platform-ini.js @@ -0,0 +1,50 @@ +"use strict"; + +// On debug builds, crashing tabs results in much thinking, which +// slows down the test and results in intermittent test timeouts, +// so we'll pump up the expected timeout for this test. +requestLongerTimeout(2); + +SimpleTest.expectChildProcessCrash(); + +add_task(async function test_browser_crashed_no_platform_ini_event() { + info("Waiting for oop-browser-buildid-mismatch event."); + + Services.telemetry.clearScalars(); + is( + getFalsePositiveTelemetry(), + undefined, + "Build ID mismatch false positive count should be undefined" + ); + + ok(await ensureBuildID(), "System has correct platform.ini"); + + let profD = Services.dirsvc.get("GreD", Ci.nsIFile); + let platformIniOrig = await IOUtils.readUTF8( + PathUtils.join(profD.path, "platform.ini") + ); + + await IOUtils.remove(PathUtils.join(profD.path, "platform.ini")); + + setBuildidMatchDontSendEnv(); + await forceCleanProcesses(); + let eventPromise = getEventPromise( + "oop-browser-buildid-mismatch", + "no-platform-ini" + ); + let tab = await openNewTab(false); + await eventPromise; + await IOUtils.writeUTF8( + PathUtils.join(profD.path, "platform.ini"), + platformIniOrig, + { flush: true } + ); + unsetBuildidMatchDontSendEnv(); + + is( + getFalsePositiveTelemetry(), + undefined, + "Build ID mismatch false positive count should be undefined" + ); + await closeTab(tab); +}); diff --git a/browser/base/content/test/tabcrashed/head.js b/browser/base/content/test/tabcrashed/head.js index 7f106d363f1d..552ad9ab30f0 100644 --- a/browser/base/content/test/tabcrashed/head.js +++ b/browser/base/content/test/tabcrashed/head.js @@ -146,42 +146,26 @@ function prepareNoDump() { } const kBuildidMatchEnv = "MOZ_BUILDID_MATCH_DONTSEND"; +const envService = Cc["@mozilla.org/process/environment;1"].getService( + Ci.nsIEnvironment +); function setBuildidMatchDontSendEnv() { - const envService = Cc["@mozilla.org/process/environment;1"].getService( - Ci.nsIEnvironment - ); info("Setting " + kBuildidMatchEnv + "=1"); envService.set(kBuildidMatchEnv, "1"); - info("Set " + kBuildidMatchEnv + "=1"); } function unsetBuildidMatchDontSendEnv() { - const envService = Cc["@mozilla.org/process/environment;1"].getService( - Ci.nsIEnvironment - ); info("Setting " + kBuildidMatchEnv + "=0"); envService.set(kBuildidMatchEnv, "0"); - info("Set " + kBuildidMatchEnv + "=0"); } -function getEventPromise(eventName, eventKind, kTimeout) { +function getEventPromise(eventName, eventKind) { return new Promise(function(resolve, reject) { - /* eslint-disable mozilla/no-arbitrary-setTimeout */ - let maybeTimeout = setTimeout(() => { - ok( - false, - "Timed out waiting " + eventName + " (" + eventKind + ") event" - ); - reject(); - }, kTimeout); - info("Installing event listener (" + eventKind + ")"); window.addEventListener( eventName, event => { - info("Clear timeout for " + eventKind + " event"); - clearTimeout(maybeTimeout); ok(true, "Received " + eventName + " (" + eventKind + ") event"); info("Call resolve() for " + eventKind + " event"); resolve(); @@ -192,6 +176,15 @@ function getEventPromise(eventName, eventKind, kTimeout) { }); } +async function ensureBuildID() { + let profD = Services.dirsvc.get("GreD", Ci.nsIFile); + let platformIniOrig = await IOUtils.readUTF8( + PathUtils.join(profD.path, "platform.ini") + ); + let buildID = Services.appinfo.platformBuildID; + return platformIniOrig.indexOf(buildID) > 0; +} + async function openNewTab(forceCrash) { const PAGE = "data:text/html,A%20regular,%20everyday,%20normal%20page."; @@ -205,14 +198,21 @@ async function openNewTab(forceCrash) { }; let tab = await BrowserTestUtils.openNewForegroundTab(options); - if (forceCrash === true) { let browser = tab.linkedBrowser; - await BrowserTestUtils.crashFrame(browser, true, true, null); + await BrowserTestUtils.crashFrame( + browser, + /* shouldShowTabCrashPage */ false, + /* shouldClearMinidumps */ true, + /* BrowsingContext */ null + ); } - // Since we crashed early, we expect to have some about:blank - // Remove it to clean up + return tab; +} + +async function closeTab(tab) { + await TestUtils.waitForTick(); BrowserTestUtils.removeTab(tab); } @@ -220,3 +220,24 @@ function getFalsePositiveTelemetry() { const scalars = TelemetryTestUtils.getProcessScalars("parent"); return scalars["dom.contentprocess.buildID_mismatch_false_positive"]; } + +// The logic bound to dom.ipc.processPrelaunch.enabled will react to value +// changes: https://searchfox.org/mozilla-central/rev/ecd91b104714a8b2584a4c03175be50ccb3a7c67/dom/ipc/PreallocatedProcessManager.cpp#171-195 +// So we force flip to ensure we have no dangling process. +async function forceCleanProcesses() { + const origPrefValue = SpecialPowers.getBoolPref( + "dom.ipc.processPrelaunch.enabled" + ); + await SpecialPowers.setBoolPref( + "dom.ipc.processPrelaunch.enabled", + !origPrefValue + ); + await SpecialPowers.setBoolPref( + "dom.ipc.processPrelaunch.enabled", + origPrefValue + ); + const currPrefValue = SpecialPowers.getBoolPref( + "dom.ipc.processPrelaunch.enabled" + ); + ok(currPrefValue === origPrefValue, "processPrelaunch properly re-enabled"); +} diff --git a/browser/base/moz.build b/browser/base/moz.build index 08025978748e..2d598b9a6e6b 100644 --- a/browser/base/moz.build +++ b/browser/base/moz.build @@ -56,6 +56,7 @@ BROWSER_CHROME_MANIFESTS += [ "content/test/statuspanel/browser.ini", "content/test/sync/browser.ini", "content/test/tabcrashed/browser.ini", + "content/test/tabcrashed/browser_aboutRestartRequired.ini", "content/test/tabdialogs/browser.ini", "content/test/tabMediaIndicator/browser.ini", "content/test/tabPrompts/browser.ini", diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp index 0ccd0ec6fe95..c8c1d5073459 100644 --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -873,8 +873,6 @@ bool MessageChannel::SendBuildIDsMatchMessage(const char* aParentBuildID) { // tooling to avoid intermittent missing leakcheck NoteIntentionalCrash(XRE_GetProcessTypeString()); if (XRE_IsContentProcess()) { - // Make sure we do not die too early, as this causes weird behavior - PR_Sleep(PR_MillisecondsToInterval(1000)); return false; } }