Does V8’s Isolate::TerminateExecution cancel pending timers and promise reactions?
0 reputation · 21 May 2022, 17:06 UTC
0 reputation · 21 May 2022, 17:06 UTC
When a host invokes V8’s Isolate::TerminateExecution to enforce a timeout, the API halts the running script and clears the current microtask queue.
However, the specification does not state whether timers (setTimeout/setInterval) or promise reactions that have already been queued but not yet executed are also cancelled.
Clarifying this behavior is important for hosts that rely on termination to abort all work associated with a script, especially in environments where lingering callbacks could cause resource leaks or unintended side effects.
What guarantees does V8 provide about the fate of already‑scheduled timers and promise callbacks after TerminateExecution returns?
Does the host need to manually clear or ignore such callbacks, or does V8 treat them as implicitly cancelled?
Are there any version‑dependent differences in this behavior that hosts should be aware of?
35275 reputation · 22 May 2022, 04:11 UTC
Isolate::TerminateExecution cancels pending promise reactions (microtasks) but does not cancel pending timers. Because timers are managed by the host environment's event loop and not by the V8 engine itself, V8 has no mechanism to reach into the host's scheduler to revoke them.
When TerminateExecution is invoked, V8 halts the current execution and clears the internal microtask queue. Any promise reactions that were queued but not yet executed are discarded. This ensures that the immediate chain of asynchronous JavaScript execution is severed.
Timers are host-side constructs. Whether you are using Node.js (libuv) or a custom C++ embedder, the timer is a record in the host's memory that triggers a call back into V8 at a later time. TerminateExecution only affects the internal state of the Isolate; it does not communicate with the host's event loop. Consequently, these timers remain active and will attempt to fire as scheduled.
To fully abort all work associated with a script, the host must implement a manual cleanup strategy. Relying solely on V8's termination will lead to resource leaks or runtime errors when a stale timer attempts to execute in a terminated Isolate.
clearTimeout or the equivalent C++ API) for every tracked handle immediately after calling TerminateExecution.TerminateException if you attempt to execute further code before the termination state is fully cleared or handled.This behavior is consistent across modern V8 versions where the microtask queue is managed internally. However, if your host implements a custom microtask loop outside of V8's standard PerformMicrotaskCheckpoint, you must verify if your custom loop is also being cleared.
Verification Step: To confirm this in your environment, schedule a setTimeout and a Promise.resolve().then(). Invoke TerminateExecution and observe that the promise callback never fires, while the timer callback still attempts to enter the Isolate.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.