Repository: nodejs/node-addon-api

Issue #711: Document that the ObjectWrap example code doesn't work for multi-context usage
Created: 2020-04-27T21:48:31Z
After spending a day trying to debug why I had so many seemingly random issues with my code, I finally understood why: the object wrap example code is not compatible with a multi-context usage of the addon.
Explanation: this example set the constructor static member of the class to a reference of the constructor function but if the addon is loaded multiple time (with worker_threads for example), the value is overwritten by a new reference in the new context. That makes this reference unusable to create new instances of this wrapped class from other C++ code and makes any code wanting to use this reference in another context crash.
We should at least make sure there is a warning about this in the documentation. The best would be to provide a workaround with the new addon instance data support maybe.

Duplicate issue #725: Usage of Passing Wrapped With NodeJs' Worker Threads
Created: 2020-05-12T14:42:42Z
Hi,
Currently I am having problem in my project.
Briefly what my project does: reads mqtt output from c code and passes it inside a struct to js side. I have created a minimal example with the n-api examples using nodejs/node-addon-examples repository.
my first object contains method:
napi_value MyObject::CreateObject(napi_env env, napi_callback_info info) {
  napi_status status;

  size_t argc = 1;
  napi_value args[1];
  status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
  assert(status == napi_ok);

  napi_value instance;
  status = MyObject2::NewInstance(env, args[0], &instance);
  assert(status == napi_ok);
  return instance;
}

this method creates instance of MyObject2 and returns to js.
NewInstance for MyObject2 is:
napi_status MyObject2::NewInstance(napi_env env,
                                  napi_value arg,
                                  napi_value* instance) {
  napi_status status;

  const int argc = 1;
  napi_value argv[argc] = {arg};
  napi_value cons;
  status = napi_get_reference_value(env, constructor, &cons);
  if (status != napi_ok) return status;

  status = napi_new_instance(env, cons, argc, argv, instance);
  if (status != napi_ok) return status;

  return napi_ok;
}

finally I create and call these objects from js using following code:
function createWorker(count) {
    return new Promise((resolve, reject) => {
        const worker = new Worker(__filename, {
            workerData: count
        });
        worker.on('message', resolve);
        worker.on('error', reject);
        worker.on('exit', (code) => {
            if (code !== 0)
                reject(new Error(`Worker stopped with exit code ${code}`));
        });
    });
};

if (isMainThread) {
    createWorker(1);
    createWorker(2);
} else {
    obj1 = addon.MyObject(1);
    while(true)
        obj1.createObject(workerData);
}

behavior running this js code causes errors everytime. However when and where it causes the error and error type itself changes in each run.
sometimes I get segmentation fault. Sometimes it aborts without an error and sometimes it is the error below.

node: ../myobject.cc:212: static napi_value__* MyObject::CreateObject(napi_env, napi_callback_info): Assertion `status == napi_ok' failed.

I am suspecting this is related worker threads since I do not get any error when I run program without worker threads.
I have looked into napi_thread_safe_function however I couldn't find a way out of this.
You can find full version of example code here: https://github.com/necil/n-api-example

Closing comment (2020-05-13T07:35:43Z): I believe it is related to #711 . Please correct if I am wrong.