Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise wrapped nbind functions blocks #100

Open
neophob opened this issue Jan 4, 2018 · 2 comments
Open

Promise wrapped nbind functions blocks #100

neophob opened this issue Jan 4, 2018 · 2 comments

Comments

@neophob
Copy link

neophob commented Jan 4, 2018

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

#include <unistd.h>
void foo() {
  sleep(30);
}

#include "nbind/nbind.h"
NBIND_GLOBAL() {
  function(foo);
}

My JS code calls this function like this:

return new BlueBirdPromise((resolve) => {
    lib.foo();
    resolve();
  });

Question:

  • Is my implementation invalid?
  • what can I do that this calls do not block?
@neophob
Copy link
Author

neophob commented Jan 4, 2018

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?

@neophob
Copy link
Author

neophob commented Jan 5, 2018

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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant