I have a program that uses a v8 isolate to execute javascript code. I would like to spawn a separate thread and execute code in the isolate there too. The thread does not need to run in parallel, I am only using the separate thread so I can cancel it from a signal handler on the main thread.
I am currently using pthreads to create the separate thread. Like this:
Isolate *isolate = Isolate::New(params);
int thread_id;
pthread_create(&thread_id, NULL, call, isolate);
pthread_join(thread_id, NULL);
Where call
is the following very basic code to test locking the isolate.
void *call(void* vargs) {
Isolate *isolate = (thread_args *) vargs;
try {
v8::Locker lock(isolate);
isolate->Enter();
v8::HandleScope handle_scope(isolate);
v8::Isolate::Scope scope(isolate);
/* use isolate exclusively in here */
isolate->Exit();
} catch catch (int err) {
/* log error */
}
}
The above yields the following stack trace:
#
# Fatal error in ../src/api/api.h, line 409
# Debug check failed: blocks_.empty().
#
#
#
#FailureMessage Object: 0x16b612c88
==== C stack trace ===============================
0x0000000115378eb0 v8::base::debug::StackTrace::StackTrace() 24
0x0000000115354f3c v8::platform::(anonymous namespace)::PrintStackTrace() 116
0x0000000115362d1c V8_Fatal(char const*, int, char const*, ...) 268
0x0000000115362740 std::__1::enable_if<((!(std::is_function<std::__1::remove_pointer<char>::type>::value)) && (!(std::is_enum<char>::value))) && (has_output_operator<char, v8::base::CheckMessageStream>::value), std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>::type v8::base::PrintCheckOperand<char>(char) 0
0x00000001153f69e4 v8::internal::HandleScopeImplementer::Free() 216
0x000000011567c02c v8::internal::ThreadManager::FreeThreadResources() 164
0x000000011567c484 v8::Locker::~Locker() 76
0x0000000115340ca0 call(void*) 144
0x000000018f2e626c _pthread_start 148
0x000000018f2e108c thread_start 8
It looks like the Locker destructor is trying to free resources that haven't been allocated properly. Is there a data structure or method I need to call to ensure these resources a properly allocated when using threads and lockers?
CodePudding user response:
The thread does not need to run in parallel
You do not need to lock withv8::Locker lock(isolate);
Debug check failed: blocks_.empty().
You don't seem to enter the isolatev8::Isolate::Scope scope(isolate);
after the lock.
void *call(void* vargs) {
Isolate *isolate = (thread_args *) vargs;
try {
v8::Locker lock(isolate);
v8::Isolate::Scope scope(isolate);
/* use isolate exclusively in here */
} catch catch (int err) {
/* log error */
}
return nullptr;
}
Just tried. Can not reproduce. Works well.
void call(v8::Isolate *isolate) {
v8::Locker lock(isolate);
v8::Isolate::Scope scope(isolate);
}
int main(int argc, char *argv[]) {
auto platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
auto *allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
v8::Isolate::CreateParams params;
params.array_buffer_allocator = allocator;
auto *isolate = v8::Isolate::New(params);
std::thread thread(call, isolate);
thread.join();
isolate->Dispose();
v8::V8::Dispose();
v8::V8::DisposePlatform();
}