2017-08-09 40 views
2

我寫使用nbind - GitHub link對於大多數的事情,Nan - GitHub link調用回調異步C++插件。當我只調用一次回調時,它的工作原理是完美的。但是當我調用回調兩次時,它給出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; 
}; 

回答

1

你的類使用AsyncQueueWorker調用CallbackRunner,但AsyncQueueWorker調用AsyncExecuteComplete回調完成後,進而調用worker->Destroy()。從nan.hAsyncQueueWorker代碼:

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版本

1

你不能有兩個線程調用到相同的V8實例兼任。您需要小心鎖定以確保在任何時間點只有一個線程與V8進行交互。

+0

嗨!我應該添加儲物櫃嗎? –

+0

是的,儲物櫃是達到此目的的一種方法。 (另一個問題是,是否有多個線程對您的用例是有幫助的;或者讓所有這些線程都自己回調V8是最優雅或最高效的解決方案。由於您沒有提供進一步的細節,因此我無法給出任何建議) – jmrk

+0

謝謝你的建議:)這個例子只是模擬我真正的程序所做的事情。它是('in C++')在執行期間在它自己的線程中調用應該在JavaScript中調用的回調函數。澄清需要哪些細節?我會很樂意分享它) –

相關問題