Commit 824ae14c authored by Benedikt Meurer's avatar Benedikt Meurer Committed by V8 LUCI CQ

[debug] Cleanup properly when microtask execution is terminated.

When a terminate_exception is raised while executing one of the promise
related jobs on the microtask queue, we don't clean up properly, leaving
the async stack in the inspector in an inconsistent state, not cleaning
up the promise stack on the Isolate, and also not resetting the global
current_microtask slot. This CL adds appropriate logic to perform the
correct cleanup.

Fixed: chromium:1297964
Change-Id: I4ec64405d4c66bfe1f0115e7039866447fb10f02
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3471815
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79162}
parent dfab3f44
......@@ -5001,6 +5001,54 @@ void Isolate::OnPromiseAfter(Handle<JSPromise> promise) {
if (debug()->is_active()) PopPromise();
}
void Isolate::OnTerminationDuringRunMicrotasks() {
// This performs cleanup for when RunMicrotasks (in
// builtins-microtask-queue-gen.cc) is aborted via a termination exception.
// This has to be kept in sync with the code in said file. Currently this
// includes:
//
// (1) Resetting the |current_microtask| slot on the Isolate to avoid leaking
// memory (and also to keep |current_microtask| not being undefined as an
// indicator that we're currently pumping the microtask queue).
// (2) Empty the promise stack to avoid leaking memory.
// (3) If the |current_microtask| is a promise reaction or resolve thenable
// job task, then signal the async event delegate and debugger that the
// microtask finished running.
//
// Reset the |current_microtask| global slot.
Handle<Microtask> current_microtask(
Microtask::cast(heap()->current_microtask()), this);
heap()->set_current_microtask(ReadOnlyRoots(this).undefined_value());
// Empty the promise stack.
while (PopPromise()) {
}
if (current_microtask->IsPromiseReactionJobTask()) {
Handle<PromiseReactionJobTask> promise_reaction_job_task =
Handle<PromiseReactionJobTask>::cast(current_microtask);
Handle<HeapObject> promise_or_capability(
promise_reaction_job_task->promise_or_capability(), this);
if (promise_or_capability->IsPromiseCapability()) {
promise_or_capability = handle(
Handle<PromiseCapability>::cast(promise_or_capability)->promise(),
this);
}
if (promise_or_capability->IsJSPromise()) {
OnPromiseAfter(Handle<JSPromise>::cast(promise_or_capability));
}
} else if (current_microtask->IsPromiseResolveThenableJobTask()) {
Handle<PromiseResolveThenableJobTask> promise_resolve_thenable_job_task =
Handle<PromiseResolveThenableJobTask>::cast(current_microtask);
Handle<JSPromise> promise_to_resolve(
promise_resolve_thenable_job_task->promise_to_resolve(), this);
OnPromiseAfter(promise_to_resolve);
}
SetTerminationOnExternalTryCatch();
}
void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
promise_reject_callback_ = callback;
}
......
......@@ -960,6 +960,7 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
void OnPromiseThen(Handle<JSPromise> promise);
void OnPromiseBefore(Handle<JSPromise> promise);
void OnPromiseAfter(Handle<JSPromise> promise);
void OnTerminationDuringRunMicrotasks();
// Re-throw an exception. This involves no error reporting since error
// reporting was handled when the exception was thrown originally.
......
......@@ -4,8 +4,8 @@
#include "src/execution/microtask-queue.h"
#include <stddef.h>
#include <algorithm>
#include <cstddef>
#include "src/api/api-inl.h"
#include "src/base/logging.h"
......@@ -187,7 +187,7 @@ int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
size_ = 0;
start_ = 0;
DCHECK(isolate->has_scheduled_exception());
isolate->SetTerminationOnExternalTryCatch();
isolate->OnTerminationDuringRunMicrotasks();
OnCompleted(isolate);
return -1;
}
......
......@@ -26,6 +26,7 @@
'inspector/endless-loop': [SKIP],
'inspector/invalid': [SKIP],
'inspector/regress-1166549': [SKIP],
'inspector/regress-1297964': [SKIP],
}], # third_party_heap
]
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment