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

ThreadSafeFunction : The exception is threw in CPP, but not JS. #669

Closed
haha3344 opened this issue Feb 9, 2020 · 7 comments
Closed

ThreadSafeFunction : The exception is threw in CPP, but not JS. #669

haha3344 opened this issue Feb 9, 2020 · 7 comments

Comments

@haha3344
Copy link

haha3344 commented Feb 9, 2020

I'm using ThreadSafeFunction to implement callbacks from CPP to JS. If an exception occur in JavaScript, it will be threw in CPP, but not JS.

The test project can be found here

Environment

  • ubuntu 18.06
  • node 10.16.3
  • node-addon-api 1.0.0

SyncCallback Example(the right way)

  • cpp code
// https://github.com/nodejs/node-addon-examples/tree/master/3_callbacks/node-addon-api
void SyncCallback(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Function cb = info[0].As<Napi::Function>();
  cb.Call(env.Global(), {Napi::String::New(env, "hello SyncCallback ")});
}
  • js code, let s = sssss will throw an exception
function callBack(msg) {
  console.log(msg);
  let s = sssss
  console.log(msg);
}

addon.syncCallback(callBack);
  • run the JS code, it will throw an exception in JS
hello SyncCallback 
/home/haha/node-addon-api/addon.js:13
addon.syncCallback(callBack);
      ^

ReferenceError: sssss is not defined
    at callBack (/home/YaoXin19/node-addon-api/addon.js:5:11)
    at Object.<anonymous> (/home/YaoXin19/node-addon-api/addon.js:13:7)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)

AsyncCallback using ThreadSafeFunction

  • cpp code
// https://github.com/nodejs/node-addon-api/blob/master/doc/threadsafe_function.md
Napi::ThreadSafeFunction tsfn;
std::thread nativeThread;
void AsyncCallback(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  tsfn= Napi::ThreadSafeFunction::New(
			info.Env(),
			info[0].As<Napi::Function>(),  // JavaScript function called asynchronously
			"Resource Name",         // Name
			0,                       // Unlimited queue
			1,                       // Only one thread will use this initially
			[](Napi::Env) {        // Finalizer used to clean threads up
			  nativeThread.join();
		});

    nativeThread = std::thread([](){
      auto callback = []( Napi::Env env, Napi::Function jsCallback) {
      //try {
        jsCallback.Call(env.Global(), {Napi::String::New(env, "hello AsyncCallback")});
      //} catch(const std::exception& e) {
      // }
    };

    napi_status status = tsfn.BlockingCall(callback );
    tsfn.Release();
  });
}
  • js code, let s = sssss will throw an exception
function callBack(msg) {
  console.log(msg);
  let s = sssss
  console.log(msg);
}
addon.asyncCallback(callBack);
  • run the JS code, the exception is threw in CPP
hello AsyncCallback
terminate called after throwing an instance of 'Napi::Error'
  what():  sssss is not defined
Aborted (core dumped)

Question

When using ThreadSafeFunction, how to throw exceptions in JS like the SyncCallback Example?

@haha3344 haha3344 changed the title ThreadSafeFunction : The exception was threw in CPP, but not JS. ThreadSafeFunction : The exception is threw in CPP, but not JS. Feb 9, 2020
@legendecas
Copy link
Member

How would you like to handle the thrown errors in an async way? They cannot be caught with try...catch block.

@haha3344
Copy link
Author

How would you like to handle the thrown errors in an async way? They cannot be caught with try...catch block.

I mean to use the simple example above to show my problem.

I do this becasue I have a CPP addon, which has a worker thread to callback some data and I need to transform these data from CPP to JS.

When using ThreadSafeFunction, the async callback works.

Then I need to write some JS code to deal with these data. If I make some mistakes in JS code, the exception will be thrown in CPP, but not in JS.

Is there a way to handle the exception in JS, but not in CPP?

Thank you.

@legendecas
Copy link
Member

legendecas commented Feb 10, 2020

The error was thrown into c++ (which is not quite accurate, the errors are still on JavaScript land, but c++ addon have to handle it or the process had to crash) because the one who called the throwing JavaScript function is the c++ addon.

You may wrap the JavaScript callback to handle the exceptions early in JavaScript:

function wrap(fn) {
  return function wrapper(...args) {
    try {
      return fn.apply(this, args);
    } catch (e) {
      // do what you'd like to do with the error `e` here.
    }
  };
}
function callback(msg) {
  console.log(msg);
  let s = sssss
  console.log(msg);
}
addon.asyncCallback(wrap(callback));

@haha3344
Copy link
Author

@legendecas Thanks for you reply. It works.

@haha3344 haha3344 reopened this Feb 11, 2020
@haha3344
Copy link
Author

Sorry to open this issue again.

Using the wrap function, I can catch the exceptions early in JavaScript.

But I still have an another question.

When I use the CPP addon in electron, the syncCallback could show the exception on the DevTools like this

1

but the asyncCallback with wrap wouldn't. If I throw the exception in the CATCH block again, it makes the electron demo crash. asyncCallback without wrap make the electron demo crash directly.

Is there way to make the asyncCallback do the same way like syncCallback in electron?
Showing the exceptions on the DevTools and do not make the electron crash.

The electron demo can be found here

@legendecas
Copy link
Member

You can print the error with console.error.

@haha3344
Copy link
Author

@legendecas Thanks for your reply.

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

2 participants