Question

I'm experimenting with V8 at the moment. I want to be able to run some (possibly long-running) javascript in one thread and then be able to terminate the execution "gracefully" at will from another thread.

I've written this simple snippet to test the concept of Lockers and the usage of TerminateExecution:

void breaker( Isolate* isolate, int tid ) {

    getchar();      //wait for keyboard input on stdin

    std::cout << "Breaking V8 execution" << std::endl;

    v8::Locker locker( isolate );       //lock the isolate
    v8::V8::TerminateExecution( tid );  //and terminate it
}

int main( int argc, char **argv ) {

    if( argc != 2 ) {
        std::cout << "No script name given" << std::endl;
        return 1;
    }

    Isolate* isolate = Isolate::New();              //create a new isolate
    Isolate::Scope isolateScope( isolate );         //enter it

    v8::Locker locker( isolate );                   //lock the isolate
    v8::Locker::StartPreemption( 100 );             //and start preemption

    v8::HandleScope handle_scope( isolate );        //open a new handle scope


    /*** inject a console object into the global context ***/
    v8::Handle<v8::ObjectTemplate> globalTemplate = v8::ObjectTemplate::New();

    Handle<Context> context = Context::New( NULL, globalTemplate );
    v8::Context::Scope context_scope( context );

    Console* console = new Console;
    Handle<Object> jsConsole = wrap_console( isolate, console );
    expose_property( jsConsole, String::New( "log" ), InvocationCallback( Console::consoleLog ) );
    context->Global()->Set( String::New( "console" ), jsConsole, v8::ReadOnly );
    /*******************************************************/


    //read a javascript file supplied via console
    std::string contents = read_file( argv[1] );
    v8::Handle<v8::String> js = v8::String::New( contents.c_str() );

    v8::TryCatch try_catch;
    v8::Handle<v8::Script> script = v8::Script::Compile( js );

    if( script.IsEmpty() ) {
        report_exception( try_catch );
    }

    //start the breaker thread
    std::thread th( breaker, isolate, v8::V8::GetCurrentThreadId() );

    log_info( "running script" );
    script->Run();
    log_info( "Script execution finished" );

    th.join();
}

However, I always get a segfault on the terminateExecution() call. What am I doing wrong here?

thanks for any help

Was it helpful?

Solution

The v8::V8::GetCurrentThreadId() and v8::V8::TerminateExecution(int) methods have been removed from the V8 API. I recommend that you don't use them. The preemption feature is probably also not long for this world.

Instead, simply call v8::V8::TerminateExecution(v8::Isolate*). And don't lock the isolate in your breaker thread, as doing so will block until your runner thread releases the isolate, which it won't do until script execution is finished.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top