Bug 1713320, ensure idle tasks get run, r=bas

If IdleTaskManager is suspended and non-idle task _is_run_, nothing seems to guarantee idle tasks get run later.
Calling UpdateCachedIdleDeadline triggers child->parent->child ipc messages if needed and ends up enabling
IdleTaskManager.

Differential Revision: https://phabricator.services.mozilla.com/D116316
This commit is contained in:
Olli Pettay 2021-05-31 13:32:36 +00:00
Родитель 5b9b440b1f
Коммит 73bad4abf2
4 изменённых файлов: 61 добавлений и 0 удалений

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

@ -711,6 +711,7 @@ skip-if = xorigin # JavaScript error: http://mochi.test:8888/tests/SimpleTest/Si
[test_NodeIterator_mutations_1.xhtml]
[test_NodeIterator_mutations_2.html]
[test_NodeIterator_mutations_3.html]
[test_nested_event_loop_spin_and_idle_tasks.html]
[test_nodelist_holes.html]
[test_open_null_features.html]
[test_openDialogChromeOnly.html]

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

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Nested event loop spinning and idle task handling</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
<script>
if (!location.search.includes("newpage")) {
SimpleTest.waitForExplicitFinish();
var win = window.open(this.location + "?newpage");
win.onload = function() {
var xhr = new XMLHttpRequest();
// Spin the event loop using a synchronous XMLHttpRequest.
xhr.open("GET", "slow.sjs", false);
xhr.send();
ok(win.didRunIdleCallback, "Should have run an idle callback.");
win.close();
SimpleTest.finish();
}
} else {
var didRunIdleCallback = false;
requestIdleCallback(function() {
didRunIdleCallback = true;
});
}
</script>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
</body>
</html>

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

@ -72,6 +72,13 @@ class IdlePeriodState {
mCachedIdleDeadline = GetIdleDeadlineInternal(false, aProofOfUnlock);
}
// If we have local idle deadline, but don't have an idle token, this will
// request such from the parent process when this is called in a child
// process.
void RequestIdleDeadlineIfNeeded(const MutexAutoUnlock& aProofOfUnlock) {
GetIdleDeadlineInternal(false, aProofOfUnlock);
}
// Reset our cached idle deadline, so we stop allowing idle runnables to run.
void ClearCachedIdleDeadline() { mCachedIdleDeadline = TimeStamp(); }

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

@ -620,6 +620,25 @@ bool TaskController::ExecuteNextTaskOnlyMainThreadInternal(
do {
taskRan = DoExecuteNextTaskOnlyMainThreadInternal(aProofOfLock);
if (taskRan) {
if (mIdleTaskManager && mIdleTaskManager->mTaskCount &&
mIdleTaskManager->IsSuspended(aProofOfLock)) {
uint32_t activeTasks = mMainThreadTasks.size();
for (TaskManager* manager : mTaskManagers) {
if (manager->IsSuspended(aProofOfLock)) {
activeTasks -= manager->mTaskCount;
} else {
break;
}
}
if (!activeTasks) {
// We have only idle (and maybe other suspended) tasks left, so need
// to update the idle state. We need to temporarily release the lock
// while we do that.
MutexAutoUnlock unlock(mGraphMutex);
mIdleTaskManager->State().RequestIdleDeadlineIfNeeded(unlock);
}
}
break;
}