3

我正在使用nbind 编写 C++ 插件 -大多数事情的GitHub 链接和 Nan -用于异步调用回调的 GitHub 链接。当我只调用一次回调时,它可以完美运行。但是当我调用回调两次时,它给出了Segmentation fault (core dumped). 使用 找不到错误gdb。这是 JS 和 C++ 代码(使用编译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++插件的代码

//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;
};
4

2 回答 2

4

您的类用于AsyncQueueWorker调用CallbackRunner, 但在回调完成后AsyncQueueWorker调用AsyncExecuteComplete,这反过来又调用worker->Destroy(). 请参阅以下AsyncQueueWorker代码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()将删除CallbackRunner该类以及Nan::Callback您提供给其构造函数的类。这就是为什么在尝试第二次调用此回调时出现分段错误的原因。

您最好将课程建立在Nan::AsyncProgressQueueWorker而不是Nan::AsyncWorker. AsyncProgressQueueWorker继承AsyncWorker,它允许您像AsyncWorker这样做一样从主线程安排工作,但它为您提供了一个ExecutionProgress类,允许您在原始计划作业运行时使用任何线程多次回调主线程。

Nan::AsyncProgressQueueWorker在版本中添加到NAN2.8.0

于 2017-11-25T19:51:35.900 回答
1

您不能让两个线程同时调用同一个 V8 实例。您需要仔细锁定以确保在任何时间点只有一个线程与 V8 交互。

于 2017-08-09T17:43:48.463 回答