2017-08-09 25 views
2

ほとんどの場合nbind - GitHub linkを使用し、非同期コールバックコールの場合はNan - GitHub linkを使用してC++アドオンを作成しています。コールバックを1回だけ呼び出すと、完璧に機能します。しかし、コールバックを2回呼び出すと、Segmentation fault (core dumped)となります。 gdbを使用してエラーが見つかりませんでした。ここでJSとC++コード(node-gyp configure buildを使用してコンパイルする)は、次のとおりです。コールバック関数を2回呼び出すと、セグメンテーションフォールトが発生します.NN

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

答えて

1

あなたのクラスはCallbackRunnerを呼び出すためにAsyncQueueWorkerを使用していますが、コールバックが順番にworker->Destroy()を呼び出す、実行された後AsyncQueueWorkerAsyncExecuteCompleteを呼び出します。 nan.hからAsyncQueueWorkerコードを参照してください:

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()は、あなたがそのコンストラクタに供給Nan::Callbackとともに、CallbackRunnerクラスを削除します。これは、このコールバックを2度目にコールしようとするとセグメンテーションフォルトが発生する理由です。

ではなく、Nan::AsyncProgressQueueWorkerにあなたのクラスを載せるほうがよいかもしれません。 AsyncProgressQueueWorkerAsyncWorkerを継承しており、AsyncWorkerのようにメインスレッドからの作業をスケジュールすることができますが、元のスケジュールされたジョブを何回でもメインスレッドにコールバックするためのスレッドを使用できるExecutionProgressクラスが用意されていますが走っています。

Nan::AsyncProgressQueueWorkerはバージョン2.8.0

1

あなたが同時に同じV8インスタンスを呼び出す二つのスレッドを持つことができません。どの時点でも、1つのスレッドだけがV8とやりとりするように、注意深くロックする必要があります。

+0

こんにちはにNANに追加されました!私はロッカーを追加する必要がありますか? –

+0

はい、ロッカーはこれを達成するための1つの方法です。 (もう1つの質問は、複数のスレッドを持つことがあなたのユースケースに役立つかどうか、あるいはこれらすべてのスレッドがV8に独自のコールバックを実行するかどうかです。これ以上の詳細は提供していないので、 ) – jmrk

+0

アドバイスありがとうございました:)この例は、私の実際のプログラムのシミュレーションです。実行中にJavaScriptで呼び出される必要があるのは、独自のスレッド内の( 'in C++')コールコールバックです。明確化のためにどのような詳細が必要でしょうか?私はそれを共有することを喜んでします;) –

関連する問題