Skip to content

Commit 2aff060

Browse files
committed
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.
1 parent 351bef6 commit 2aff060

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

test-app/runtime/src/main/cpp/EventLoop.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,16 +736,18 @@ EventLoop::PumpResult EventLoop::PumpUntil(double deadlineSeconds,
736736
const auto deadline = std::chrono::steady_clock::now() +
737737
std::chrono::duration<double>(deadlineSeconds);
738738
for (;;) {
739-
if (settled()) {
740-
return PumpResult::kSettled;
741-
}
742739
// Both probes: IsExecutionTerminating is true only while JS frames
743740
// unwind with the termination exception active, so a pump parked with
744741
// nothing queued would never observe TerminateExecution through it.
742+
// Termination outranks settlement: consuming a settled result means
743+
// running more JS, which a terminating isolate must not do.
745744
if (terminationRequested_.load(std::memory_order_acquire) ||
746745
isolate_->IsExecutionTerminating()) {
747746
return PumpResult::kTerminated;
748747
}
748+
if (settled()) {
749+
return PumpResult::kSettled;
750+
}
749751
if (IsStopped()) {
750752
// a stopped loop drops every post, so nothing can settle anymore
751753
return PumpResult::kTerminated;
@@ -771,7 +773,9 @@ EventLoop::PumpResult EventLoop::PumpUntil(double deadlineSeconds,
771773
}
772774
}
773775
if (settled()) {
774-
return PumpResult::kSettled;
776+
// back through the loop head, where termination outranks the
777+
// settlement this drain produced
778+
continue;
775779
}
776780
if (ranLooperWork == 0) {
777781
WaitForInternalWork(10, /*pumpDeliverable=*/drainLooperWork);

0 commit comments

Comments
 (0)