Invoking some callback function twice leads to Segmentation fault: Nan

六眼飞鱼酱① 提交于 2019-12-11 03:35:16

问题


I am writing C++ addon using nbind - GitHub link for most thing and Nan - GitHub link for calling callbacks asynchronous. When I invoke callback only once, it works perfect. But When I invoke callback twice it gives Segmentation fault (core dumped). Couldn't find error using gdb. Here is JS and C++ codes(compiling using node-gyp configure build):

//main.js code
var nbind = require('nbind');
var lib = nbind.init().lib;

lib.HeaderExample.callJS(function(a) {
console.log("result" + a);
});

lib.HeaderExample.startThread();
lib.HeaderExample.startThread(); 

C++ addon's code

//c++ code
class CallbackRunner : public Nan::AsyncWorker {
public:
    CallbackRunner(Nan::Callback *callback)
            : AsyncWorker(callback) {}
    void Execute () {}
    void HandleOKCallback () {
        std::cout << "running HandleOKCallback in thread " << std::this_thread::get_id() << std::endl;
        Nan::HandleScope scope;
        v8::Local<v8::Value> argv[] = {
                Nan::New<v8::Number>(10)
        };
        callback->Call(1, argv);
    }
};

class HeaderExample {
public:
    static void callJS(nbind::cbFunction &callback) {
        std::cout << "running callJS in thread " << std::this_thread::get_id() << std::endl;
        m_onInitialisationStarted = new nbind::cbFunction(callback);
        Nan::Callback *callbackNan = new Nan::Callback(m_onInitialisationStarted->getJsFunction());
        runner = new CallbackRunner(callbackNan);
    }
    static void startThread() {
        std::cout << "it is here";
        std::thread threadS(some);
        threadS.join();
    }
    static void some() {
        std::cout << "running some in thread: " << std::this_thread::get_id() << std::endl;
        if(runner){
        AsyncQueueWorker(runner);
        }
    }
    inline static nbind::cbFunction *m_onInitialisationStarted = 0;
    inline static CallbackRunner *runner;
};

回答1:


Your class uses AsyncQueueWorker to invoke the CallbackRunner, but AsyncQueueWorker calls AsyncExecuteComplete after the callback is done, which in turn calls worker->Destroy(). See the AsyncQueueWorker code from nan.h:

inline void AsyncExecute (uv_work_t* req) {
  AsyncWorker *worker = static_cast<AsyncWorker*>(req->data);
  worker->Execute();
}

inline void AsyncExecuteComplete (uv_work_t* req) {
  AsyncWorker* worker = static_cast<AsyncWorker*>(req->data);
  worker->WorkComplete();
  worker->Destroy();
}

inline void AsyncQueueWorker (AsyncWorker* worker) {
  uv_queue_work(
      uv_default_loop()
    , &worker->request
    , AsyncExecute
    , reinterpret_cast<uv_after_work_cb>(AsyncExecuteComplete)
  );
}

worker->Destroy() will delete the CallbackRunner class, along with the Nan::Callback that you fed to its constructor. That is the reason why you get a segmentation fault when attempting to call this callback a second time.

You might be better off basing your class on Nan::AsyncProgressQueueWorker instead of Nan::AsyncWorker. AsyncProgressQueueWorker inherits AsyncWorker and it allows you to schedule work from the main thread just as AsyncWorker does, but it provides you with an ExecutionProgress class that allows you to use any thread to call back into the main thread any number of times while the original scheduled job is running.

Nan::AsyncProgressQueueWorker was added to NAN in version 2.8.0




回答2:


You can't have two threads calling into the same V8 instance concurrently. You'll need careful locking to make sure that only one thread interacts with V8 at any point in time.



来源:https://stackoverflow.com/questions/45589254/invoking-some-callback-function-twice-leads-to-segmentation-fault-nan

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!