Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
fix(runtime): let termination outrank settlement in PumpUntil
A Terminate() racing an entry that genuinely settles returned kSettled,
and the caller went on to run JS (worker queue enable, drains) on an
isolate with TerminateExecution pending. Both settle probes now funnel
through the loop head, where the termination check comes first; a
fulfilled module's registration is untouched on that path, only its
result is discarded.
  • Loading branch information
edusperoni committed Aug 20, 2026
commit 2aff060a718090cc849ea744563fa554baceb617
12 changes: 8 additions & 4 deletions test-app/runtime/src/main/cpp/EventLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,16 +736,18 @@ EventLoop::PumpResult EventLoop::PumpUntil(double deadlineSeconds,
const auto deadline = std::chrono::steady_clock::now() +
std::chrono::duration<double>(deadlineSeconds);
for (;;) {
if (settled()) {
return PumpResult::kSettled;
}
// Both probes: IsExecutionTerminating is true only while JS frames
// unwind with the termination exception active, so a pump parked with
// nothing queued would never observe TerminateExecution through it.
// Termination outranks settlement: consuming a settled result means
// running more JS, which a terminating isolate must not do.
if (terminationRequested_.load(std::memory_order_acquire) ||
isolate_->IsExecutionTerminating()) {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
return PumpResult::kTerminated;
}
if (settled()) {
return PumpResult::kSettled;
}
if (IsStopped()) {
// a stopped loop drops every post, so nothing can settle anymore
return PumpResult::kTerminated;
Expand All @@ -771,7 +773,9 @@ EventLoop::PumpResult EventLoop::PumpUntil(double deadlineSeconds,
}
}
if (settled()) {
return PumpResult::kSettled;
// back through the loop head, where termination outranks the
// settlement this drain produced
continue;
}
if (ranLooperWork == 0) {
WaitForInternalWork(10, /*pumpDeliverable=*/drainLooperWork);
Expand Down