Backed out 2 changesets (bug 1777198) for causing build bustage in dom/ipc/ProcessHangMonitor.cpp CLOSED TREE

Backed out changeset 472fe2d7af01 (bug 1777198)
Backed out changeset 0b9cb5b44360 (bug 1777198)
This commit is contained in:
Sandor Molnar 2022-08-02 14:08:45 +03:00
parent 8ec529562a
commit 646227cd7d
9 changed files with 8 additions and 239 deletions

View File

@ -1652,7 +1652,6 @@ const nsACString& ContentParent::GetRemoteType() const { return mRemoteType; }
static StaticRefPtr<nsIAsyncShutdownClient> sXPCOMShutdownClient;
static StaticRefPtr<nsIAsyncShutdownClient> sProfileBeforeChangeClient;
static StaticRefPtr<nsIAsyncShutdownClient> sQuitApplicationGrantedClient;
void ContentParent::Init() {
MOZ_ASSERT(sXPCOMShutdownClient);
@ -1723,7 +1722,6 @@ void ContentParent::MaybeBeginShutDown(uint32_t aExpectedBrowserCount,
// We're dying now, prevent anything from re-using this process.
MarkAsDead();
SignalImpendingShutdownToContentJS();
StartForceKillTimer();
if (aSendShutDown) {
@ -1801,12 +1799,7 @@ void ContentParent::ShutDownProcess(ShutDownMethod aMethod) {
__LINE__);
mShutdownPending = true;
// Start the force-kill timer if we haven't already.
// This can happen if we shutdown a process while launching or
// because it is removed from the cached processes pool.
if (!mForceKillTimer) {
SignalImpendingShutdownToContentJS();
StartForceKillTimer();
}
} else {
MaybeLogBlockShutdownDiagnostics(
this, "ShutDownProcess: !!! Send shutdown message failed! !!!",
@ -2374,6 +2367,8 @@ void ContentParent::StartForceKillTimer() {
return;
}
NotifyImpendingShutdown();
int32_t timeoutSecs = StaticPrefs::dom_ipc_tabs_shutdownTimeoutSecs();
if (timeoutSecs > 0) {
NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
@ -3583,71 +3578,14 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMProcessParent)
NS_INTERFACE_MAP_END
class RequestContentJSInterruptRunnable final : public Runnable {
public:
explicit RequestContentJSInterruptRunnable(PProcessHangMonitorParent* aActor)
: Runnable("dom::RequestContentJSInterruptRunnable"),
mHangMonitorActor(aActor) {}
NS_IMETHOD Run() override {
MOZ_ASSERT(mHangMonitorActor);
Unused << mHangMonitorActor->SendRequestContentJSInterrupt();
return NS_OK;
}
private:
// The end-of-life of ContentParent::mHangMonitorActor is bound to
// ContentParent::ActorDestroy and then HangMonitorParent::Shutdown
// dispatches a shutdown runnable to this queue and waits for it to be
// executed. So the runnable needs not to care about keeping it alive,
// as it is surely dispatched earlier than the
// HangMonitorParent::ShutdownOnThread.
PProcessHangMonitorParent* mHangMonitorActor;
};
void ContentParent::SignalImpendingShutdownToContentJS() {
if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown)) {
MaybeLogBlockShutdownDiagnostics(
this, "BlockShutdown: NotifyImpendingShutdown.", __FILE__, __LINE__);
NotifyImpendingShutdown();
if (mHangMonitorActor &&
StaticPrefs::dom_abort_script_on_child_shutdown()) {
MaybeLogBlockShutdownDiagnostics(
this, "BlockShutdown: RequestContentJSInterrupt.", __FILE__,
__LINE__);
RefPtr<RequestContentJSInterruptRunnable> r =
new RequestContentJSInterruptRunnable(mHangMonitorActor);
ProcessHangMonitor::Get()->Dispatch(r.forget());
}
}
}
// Async shutdown blocker
NS_IMETHODIMP
ContentParent::BlockShutdown(nsIAsyncShutdownClient* aClient) {
if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdown)) {
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
mBlockShutdownCalled = true;
#endif
// Our real shutdown has not yet started. Just notify the
// impending shutdown and eventually cancel content JS.
SignalImpendingShutdownToContentJS();
if (sQuitApplicationGrantedClient) {
Unused << sQuitApplicationGrantedClient->RemoveBlocker(this);
}
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
mBlockShutdownCalled = false;
#endif
return NS_OK;
}
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
// We register two final shutdown blockers and both would call us, but if
// things go well we will unregister both as (delayed) reaction to the first
// call we get and thus never receive a second call. Thus we believe that we
// will get called only once except for quit-application-granted, which is
// handled above.
// We register two shutdown blockers and both would call us, but
// if things go well we will unregister both as (delayed) reaction
// to the first call we get and thus never receive a second call.
// Thus we believe that we will get called only once.
MOZ_ASSERT(!mBlockShutdownCalled);
mBlockShutdownCalled = true;
#endif
@ -3733,15 +3671,6 @@ static void InitShutdownClients() {
ClearOnShutdown(&sProfileBeforeChangeClient);
}
}
// TODO: ShutdownPhase::AppShutdownConfirmed is not mapping to
// QuitApplicationGranted, see bug 1762840 comment 4.
if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
rv = svc->GetQuitApplicationGranted(getter_AddRefs(client));
if (NS_SUCCEEDED(rv)) {
sQuitApplicationGrantedClient = client.forget();
ClearOnShutdown(&sQuitApplicationGrantedClient);
}
}
}
}
@ -3758,10 +3687,6 @@ void ContentParent::AddShutdownBlockers() {
sProfileBeforeChangeClient->AddBlocker(
this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, u""_ns);
}
if (sQuitApplicationGrantedClient) {
sQuitApplicationGrantedClient->AddBlocker(
this, NS_LITERAL_STRING_FROM_CSTRING(__FILE__), __LINE__, u""_ns);
}
}
void ContentParent::RemoveShutdownBlockers() {
@ -3780,9 +3705,6 @@ void ContentParent::RemoveShutdownBlockers() {
if (sProfileBeforeChangeClient) {
Unused << sProfileBeforeChangeClient->RemoveBlocker(this);
}
if (sQuitApplicationGrantedClient) {
Unused << sQuitApplicationGrantedClient->RemoveBlocker(this);
}
}
NS_IMETHODIMP

View File

@ -817,13 +817,6 @@ class ContentParent final : public PContentParent,
*/
void MarkAsDead();
/**
* Let the process know we are about to send a shutdown through a
* non-mainthread side channel in order to bypass mainthread congestion.
* This potentially cancels mainthread content JS execution.
*/
void SignalImpendingShutdownToContentJS();
/**
* Check if this process is ready to be shut down, and if it is, begin the
* shutdown process. Should be called whenever a change occurs which could

View File

@ -32,7 +32,6 @@ parent:
child:
async TerminateScript();
async RequestContentJSInterrupt();
async BeginStartingDebugger();
async EndStartingDebugger();

View File

@ -22,7 +22,6 @@
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/ipc/TaskFactory.h"
#include "mozilla/Monitor.h"
#include "mozilla/Preferences.h"
@ -111,7 +110,6 @@ class HangMonitorChild : public PProcessHangMonitorChild,
void MaybeStartPaintWhileInterruptingJS();
mozilla::ipc::IPCResult RecvTerminateScript() override;
mozilla::ipc::IPCResult RecvRequestContentJSInterrupt() override;
mozilla::ipc::IPCResult RecvBeginStartingDebugger() override;
mozilla::ipc::IPCResult RecvEndStartingDebugger() override;
@ -260,7 +258,6 @@ class HangMonitorParent : public PProcessHangMonitorParent,
const dom::CancelContentJSOptions& aCancelContentJSOptions);
void TerminateScript();
void RequestContentJSInterrupt();
void BeginStartingDebugger();
void EndStartingDebugger();
@ -347,18 +344,6 @@ HangMonitorChild::~HangMonitorChild() {
bool HangMonitorChild::InterruptCallback() {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
if (StaticPrefs::dom_abort_script_on_child_shutdown() &&
mozilla::ipc::ProcessChild::ExpectingShutdown()) {
// We preserve chrome JS from cancel, but not extension content JS.
if (!nsContentUtils::IsCallerChrome()) {
NS_WARNING(
"HangMonitorChild::InterruptCallback: ExpectingShutdown, "
"canceling content JS execution.\n");
return false;
}
return true;
}
// Don't start painting if we're not in a good place to run script. We run
// chrome script during layout and such, and it wouldn't be good to interrupt
// painting code from there.
@ -510,18 +495,6 @@ mozilla::ipc::IPCResult HangMonitorChild::RecvTerminateScript() {
return IPC_OK();
}
mozilla::ipc::IPCResult HangMonitorChild::RecvRequestContentJSInterrupt() {
MOZ_RELEASE_ASSERT(IsOnThread());
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::IPCShutdownState,
"HangMonitorChild::RecvRequestContentJSInterrupt"_ns);
// In order to cancel JS execution on shutdown, we expect that
// ProcessChild::NotifiedImpendingShutdown has been called before.
JS_RequestInterruptCallback(mContext);
return IPC_OK();
}
mozilla::ipc::IPCResult HangMonitorChild::RecvBeginStartingDebugger() {
MOZ_RELEASE_ASSERT(IsOnThread());
@ -904,14 +877,6 @@ void HangMonitorParent::TerminateScript() {
}
}
void HangMonitorParent::RequestContentJSInterrupt() {
MOZ_RELEASE_ASSERT(IsOnThread());
if (mIPCOpen) {
Unused << SendRequestContentJSInterrupt();
}
}
void HangMonitorParent::BeginStartingDebugger() {
MOZ_RELEASE_ASSERT(IsOnThread());

View File

@ -63,7 +63,3 @@ support-files =
browser_wpi_base.js
[browser_pbrowser_creation_failure.js]
skip-if = !fission
[browser_content_shutdown_with_endless_js.js]
support-files =
file_endless_js.html
file_dummy.html

View File

@ -1,85 +0,0 @@
/* 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/. */
"use strict";
const EMPTY_PAGE =
"http://mochi.test:8888/browser/dom/ipc/tests/file_dummy.html";
const HANG_PAGE =
"http://mochi.test:8888/browser/dom/ipc/tests/file_endless_js.html";
function pushPref(name, val) {
return SpecialPowers.pushPrefEnv({ set: [[name, val]] });
}
async function createAndShutdownContentProcess(url) {
info("Create and shutdown a content process for " + url);
let oldChildCount = Services.ppmm.childCount;
info("Old process count: " + oldChildCount);
let tabpromise = BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: url,
waitForLoad: true,
forceNewProcess: true,
});
let tab = await tabpromise;
// It seems that the ppmm counter is racy wrt tabpromise.
Services.tm.spinEventLoopUntil(
"browser_content_shutdown_with_endless_js",
() => Services.ppmm.childCount > oldChildCount
);
let newChildCount = Services.ppmm.childCount;
info("New process count: " + newChildCount);
ok(newChildCount == oldChildCount + 1, "Process created.");
// Start the shutdown of the child process
let tabClosed = BrowserTestUtils.waitForTabClosing(tab);
BrowserTestUtils.removeTab(tab);
ok(true, "removeTab");
Services.tm.spinEventLoopUntil(
"browser_content_shutdown_with_endless_js",
() => Services.ppmm.childCount < newChildCount
);
info("New count: " + Services.ppmm.childCount);
await tabClosed;
ok(
Services.ppmm.childCount == oldChildCount,
"Shutdown of content process complete."
);
}
add_task(async () => {
// This test is only relevant in e10s.
if (!gMultiProcessBrowser) {
ok(true, "We are not in multiprocess mode, skipping test.");
return;
}
await pushPref("dom.abort_script_on_child_shutdown", true);
// Ensure the process cache cannot interfere.
pushPref("dom.ipc.processPreload.enabled", false);
// Ensure we have no cached processes from previous tests.
Services.ppmm.releaseCachedProcesses();
// First let's do a dry run that should always succeed.
await createAndShutdownContentProcess(EMPTY_PAGE);
// Now we will start a shutdown of our content process while our content
// script is running an endless loop.
//
// If the JS does not get interrupted on shutdown, it will cause this test
// to hang.
await createAndShutdownContentProcess(HANG_PAGE);
});

View File

@ -1,15 +0,0 @@
<!doctype html>
<html>
<head><meta charset="utf-8"></head>
<script>
function hang() {
let i = 1;
while (i > 0) {
i = Date.now();
}
}
</script>
<body onload="hang()">
<h1>This is an endless JS loop</h1>
</body>
</html>

View File

@ -74,7 +74,7 @@ void ProcessChild::NotifiedImpendingShutdown() {
sExpectingShutdown = true;
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::IPCShutdownState,
"NotifiedImpendingShutdown"_ns);
"NotifyImpendingShutdown received."_ns);
}
/* static */

View File

@ -4514,12 +4514,6 @@
#endif
mirror: always
# Controls if a content script will be aborted on child process shutdown.
- name: dom.abort_script_on_child_shutdown
type: bool
value: false
mirror: always
- name: dom.max_chrome_script_run_time
type: int32_t
value: 0