Managing multiple Isolates

159 views
Skip to first unread message

Nothing to See

unread,
Aug 28, 2015, 10:39:50 PM8/28/15
to v8-users
Hello,

I have a class which manages the creation and destruction of multiple isolates.
A little bit simplified: 
When a thread requests a new isolate, a worker thread calls Isolate::New() and returns the result.
When the thread sets the isolate's status in the manager class to 'unused', which happens after the isolate has been used and is not needed anymore, the isolate
either gets re-assigned to a different thread in case a thread needs it or disposed.

Now, the problem is, that sometimes when the isolate gets disposed, I get a crash at void Heap::TearDownArrayBuffersHelper, code: isolate->array_buffer_allocator()->Free(buffer->first, buffer->second);

I am quite sure the problem is on my end, not V8 itself. It seems to me that there is some threading issue which I cannot figure out as I am not very experienced with v8 (yet).

I would appreciate any help.

Regards.

Ben Noordhuis

unread,
Aug 29, 2015, 1:19:36 PM8/29/15
to v8-u...@googlegroups.com
It's hard to say without seeing code. Are you using Lockers and
Unlockers correctly?

Nothing to See

unread,
Aug 29, 2015, 2:08:14 PM8/29/15
to v8-users
I'll describe the system more detailed.

On application start, after V8 initialization, the manager class starts a thread ('worker'). The worker accepts tasks, like creating or disposing an isolate, which means Isolates always get created and disposed from the same thread.
This is the code which cares about the above mentioned tasks:

case IsolateOperations::Create:
{
fwstdout << "> Creating new isolate" << std::endl;
v8::Isolate **ppIsolate = reinterpret_cast<v8::Isolate**>(this->m_IsolateOperationData.Isolate);
*ppIsolate = v8::Isolate::New(*reinterpret_cast<v8::Isolate::CreateParams*>(this->m_IsolateOperationData.Data));
break;
}
case IsolateOperations::Dispose:
{
fwstdout << "> Disposing isolate" << std::endl;
v8::Isolate *isolate = reinterpret_cast<v8::Isolate*>(this->m_IsolateOperationData.Isolate);
v8::Locker locker(isolate);
isolate->Dispose();
break;
}

The pointers etc. all work as they should, so this certainly has no flaws.
I experminented with lockers, but nothing I did seems to work (At first I had no lockers, well I basically tested every combination I could think of).

The test code (which is based on the 'Hello World' example program is as follows:
(Note that  JScript::JScriptInterface::GetInstance().FreeCurrentIsolate(); doesn't dispose the isolate directly, it only marks the isolate as unused. The isolate gets disposed by the worker thread.)

void Test_RunScript(Isolate *isolate, BaseFramework::String src) {
v8::Locker locker(isolate);
isolate->Enter();

Isolate::Scope isolate_scope(isolate);
{
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);

// Create a new context.
Local<Context> context = Context::New(isolate, null, CreateGlobalTemplate(isolate));

// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);

// Create a string containing the JavaScript source code.
Local<v8::String> source =
v8::String::NewFromUtf8(isolate, src.data(),
NewStringType::kNormal).ToLocalChecked();

// Compile the source code.
Local<v8::Script> script = Script::Compile(context, source).ToLocalChecked();

// Run the script to get the result.
Local<Value> result = script->Run(context).ToLocalChecked();

// Convert the result to an UTF8 string and print it.
v8::String::Utf8Value strres(result);
fwstdout << *strres << std::endl;
}

isolate->Exit();
v8::Unlocker unlocker(isolate);
}

void CreateIsolateAndRunScript(BaseFramework::String src) {
ArrayBufferAllocator allocator;
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = &allocator;

Isolate* isolate = JScript::JScriptInterface::GetInstance().NewIsolateForCurrentThread(create_params);

Test_RunScript(isolate, src);

JScript::JScriptInterface::GetInstance().FreeCurrentIsolate();
}


JScript::JScriptInterface::GetInstance().NewIsolateForCurrentThread(create_params); assigns a new 'create isolate' task and waits for the worker to finish it, then retrieves the newly created isolate.

That's pretty much all that is to it. 

Regards.

Petr B.

unread,
May 23, 2016, 10:01:21 AM5/23/16
to v8-users
@Nothing to see

Have you been able to make it works somehow? I think that I have similar issue at the end. Please see: stackoverflow.com
Hopefully I will not to need threads.....
Reply all
Reply to author
Forward
0 new messages