Repository navigation
ThreadSafeFunction : The exception is threw in CPP, but not JS. #669
Copy link
Copy link
Closed
Description
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 = ssssswill 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 = ssssswill 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?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]ThreadSafeFunction : The exception was threw in CPP, but not JS.[/-][+]ThreadSafeFunction : The exception is threw in CPP, but not JS.[/+]legendecas commentedon Feb 9, 2020
How would you like to handle the thrown errors in an async way? They cannot be caught with try...catch block.
haha3344 commentedon Feb 10, 2020
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 commentedon 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:
haha3344 commentedon Feb 10, 2020
@legendecas Thanks for you reply. It works.
haha3344 commentedon Feb 11, 2020
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
syncCallbackcould show the exception on the DevTools like thisbut the
asyncCallback with wrapwouldn't. If I throw the exception in the CATCH block again, it makes the electron demo crash.asyncCallback without wrapmake the electron demo crash directly.Is there way to make the
asyncCallbackdo the same way likesyncCallbackin electron?Showing the exceptions on the DevTools and do not make the electron crash.
The electron demo can be found here
legendecas commentedon Feb 11, 2020
You can print the error with
console.error.haha3344 commentedon Feb 11, 2020
@legendecas Thanks for your reply.