Open neophob opened 6 years ago
I setup an minimal example project, that shows the issue: https://github.com/neophob/nbind-blocking
Tested with node v6 and v8.
So I guess to fix this behaviour I should use libuv threads (either native or using wrappers like NaN should provide some help) and callbacks. can you point me to an example where this is used?
Ok the correct way to address cpu bound tasks (or tasks which run long time) is using the libuv worker threads (uv_queue_work) so the EventLoop is not blocked
I found a excellent example here: https://github.com/paulhauner/example-async-node-addon/blob/master/async-addon/async-addon.cc
but I have now the problem, that I cannot when I call
struct AsyncDeviceInfo {
uv_work_t request;
std::unique_ptr<nbind::cbFunction> cb;
};
static void WorkAsync(uv_work_t *req) {
AsyncDeviceInfo *work = static_cast<AsyncDeviceInfo *>(req->data);
sleep(3);
}
static void WorkAsyncComplete(uv_work_t *req) {
AsyncDeviceInfo *asyncDeviceInfo = static_cast<AsyncDeviceInfo *>(req->data);
(*asyncDeviceInfo->cb)(0,1);
delete asyncDeviceInfo;
}
void myExposedFunction(nbind::cbFunction cb) {
AsyncDeviceInfo *asyncDeviceInfo = new AsyncDeviceInfo();
asyncDeviceInfo->cb = std::make_unique<nbind::cbFunction>(cb);
// embed our datastructure to the request
asyncDeviceInfo->request.data = asyncDeviceInfo;
int status = uv_queue_work(uv_default_loop(), &asyncDeviceInfo->request, WorkAsync, (uv_after_work_cb) WorkAsyncComplete);
assert(status == 0);
}
When I use this code, i get this error
FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope
1: node::Abort() [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
3: v8::Utils::ReportApiFailure(char const*, char const*) [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
4: v8::internal::HandleScope::Extend(v8::internal::Isolate*) [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
5: v8::Integer::New(v8::Isolate*, int) [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
6: nbind::TypeTransformer<int, nbind::PolicyListType<> >::WireType nbind::convertToWire<int>(int) [/Users/foobar/project/node_modules/node-cec/build/Release/nbind.node]
7: nbind::TypeTransformer<void, nbind::PolicyListType<> >::Type nbind::cbWrapper<void>::call<void, int, int>(int&&, int&&) const [/Users/foobar/project/node_modules/node-cec/build/Release/nbind.node]
8: WorkAsyncComplete(uv_work_s*) [/Users/foobar/project/node_modules/node-cec/build/Release/nbind.node]
9: uv__work_done [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
10: uv__async_event [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
11: uv__async_io [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
12: uv__io_poll [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
13: uv_run [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
14: node::Start(int, char**) [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
15: start [/Users/foobar/.nvm/versions/node/v6.9.1/bin/node]
I have a c function that might take several seconds to complete. So I wrap that call as a promise in the JS part of the code. I use this code in a express server - and while the c code is running, express does not answers any requests. this means the c code blocks. here's a little example
My JS code calls this function like this:
Question: