关于PostgreSQL的PLV8扩展中V8 Isolate中断清除的技术咨询
Let's break down the root of your issue first: When you call TerminateExecution() on an Isolate and that's the last interaction before reusing it, the thread-local interrupt flag remains set—but IsExecutionTerminating() only checks for pending uncaught termination exceptions, not the interrupt flag itself. This leaves the Isolate in a "latent interrupt" state, which triggers an unexpected exception when the next query runs.
Here are two reliable approaches to fix this:
1. Unconditionally Call CancelTerminateExecution() Before Reusing the Isolate
Don't rely on IsExecutionTerminating() to decide whether to clear state. Even if it returns false, CancelTerminateExecution() resets both pending termination exceptions and the underlying interrupt flag in most V8 versions. This is the simplest fix:
// Before executing any new JS code in the reused Isolate isolate->CancelTerminateExecution();
This ensures any leftover interrupt requests from prior query cancellations are fully cleared, regardless of whether an exception was ever thrown.
2. Force Interrupt Handling with a Minimal JS Execution
If you're working with a V8 version where CancelTerminateExecution() doesn't fully reset the interrupt flag (rare, but possible), you can trigger the interrupt handling flow explicitly by running a tiny snippet of JS code, then catch and clear any resulting termination exception:
v8::HandleScope handle_scope(isolate); v8::TryCatch try_catch(isolate); // Run a minimal JS statement to force the Isolate to process the interrupt flag v8::Local<v8::Script> script = v8::Script::Compile( isolate, v8::String::NewFromUtf8(isolate, "void 0;").ToLocalChecked() ).ToLocalChecked(); script->Run(isolate); // If a termination exception was triggered, clear it if (try_catch.HasTerminated()) { isolate->CancelTerminateExecution(); }
This forces the Isolate to process the pending interrupt, throw the termination exception, and gives you a chance to catch and clear it before running your actual query code.
Key Context to Remember
The mismatch between IsExecutionTerminating() and the interrupt flag is intentional in V8's design: IsExecutionTerminating() checks for an active, uncaught termination exception, not the underlying interrupt request. So even when no exception is pending, the interrupt flag can linger if the Isolate never got a chance to process it after TerminateExecution() was called.
By combining unconditional use of CancelTerminateExecution() (and the forced JS execution fallback if needed), you can ensure the Isolate is fully reset before each new query.
内容的提问来源于stack exchange,提问作者Stephen Ingram

