Hello again,
I have a new question, this has been causing my host app to crash regularly.
I use the V8 engine in multiple threads concurrently using Isolates - works great.
However, I often need to terminate a script early due to some change in the host app. The termination must come from another thread, obviously, because the JS thread is busy doing JS things.
So, when I start a JS execution, I keep the handle of the Isolate in a mutex-protected variable that can be used from other threads.
The mutex is locked during the Terminate call, and at the point of creating and Dispose()ing of the isolate, to prevent Terminate calls on an isolate that has been Disposed.
So, in a separate thread, I call:
V8::TerminateExecution(running_isolate);
And that usually works well, UNLESS the script is currently in the middle of some of my C++ native functions.
In which case, some very strange things happen, example:
For the first half of the C++ function, everything works fine.
For the second half, suddenly calls to eg handle->ToString() start to return empty handles. That is fine, I can handle that.
But what I can't handle is when the C++ function in question is in the middle of building an Exception report,
This is what I see when the debugger catches an OS::DebugBreak():
static string GenerateExceptionReport( TryCatch const& try_catch )
{
HandleScope handle_scope;
bool y = V8::IsExecutionTerminating(); // --> false
String::Value exception(try_catch.Exception());
bool x = V8::IsExecutionTerminating(); // --> TRUE
Handle<v8::Message> message = try_catch.Message(); // --> returns empty handle
if (message.IsEmpty())
{
// etc etc, not executed as message is empty
}
int start = message->GetStartColumn(); // --> CRASH
int end = message->GetEndColumn();
It crashes/aborts on this line:
int Message::GetStartColumn() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate, "v8::Message::GetStartColumn()")) {
return kNoColumnInfo;
}
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate); // <-------------- a test fails in here
So, my question is, how SHOULD I be using TerminateExecution() ?
My first thought is that I could use a mutex to ensure that I don't call Terminate during one of my C++ functions, but what about functions that I did not write myself ?
And, I also need to test IsExecutionTerminating() at the start of all my functions, which would be annoying.
I did try using a Locker with the Terminate, but because JS is busy running, it usually doesn't ever terminate early.
I sense that I'm Doing It Wrong.
What is the trick? Can anyone please tell me?
thanks,
Paul