Errors in thread safe functions cause fatal panic
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 7.9k
- Forks
- 412
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 61
Description
I'm attempting to use ThreadSafeFunction to call JS from Rust, but if there is any error inside the JavaScript call back it panics the whole program.
This is not what I would expect, since call_async itself returns a Result which I could choose how to handle in Rust.
Example code
#[napi]
pub async fn call_x_times(
x: i32,
cb: napi::threadsafe_function::ThreadsafeFunction<
i32,
napi::threadsafe_function::ErrorStrategy::Fatal,
>,
) -> Result<i32> {
let mut sum = 0;
for n in 0..x {
let res = cb.call_async::<i32>(n).await;
println!("Result: {:?}", res);
}
Ok(sum)
}
JS code:
let total = await callXTimes(5, (i) => {
if (i > 3) {
throw new Error('JS FAILED!');
}
return i * 3;
});
Expected behavior
I thought some variant of the JS error would be available on the Result option contained.
Actual behavior.
The entire program panics:
Result: Ok(0)
Result: Ok(3)
Result: Ok(6)
Result: Ok(9)
FATAL ERROR: threadsafe_function.rs:749 Failed to convert return value in ThreadsafeFunction callback into Rust value: GenericFailure, Error: JS FAILED!
Result: Err(Error { status: GenericFailure, reason: "channel closed", maybe_raw: 0x0 })
1: 0x104679750 node::Abort() [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
2: 0x10467983c node::OOMErrorHandler(char const*, bool) [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
3: 0x104648764 napi_open_callback_scope [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
4: 0x1230888f4 napi::threadsafe_function::call_js_cb::hbe5092c2e03212da [/Users/morgante/code/grit/rewriter/packages/bridge/__generated__/bridge.darwin-arm64.node]
5: 0x10464b83c v8impl::(anonymous namespace)::ThreadSafeFunction::AsyncCb(uv_async_s*) [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
6: 0x104fac4a0 uv__async_io [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
7: 0x104fbea54 uv__io_poll [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
8: 0x104fac970 uv_run [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
9: 0x1045bd6e0 node::SpinEventLoop(node::Environment*) [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
10: 0x1046b5d4c node::NodeMainInstance::Run() [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
11: 0x1046462ec node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResult const*) [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
12: 0x1046465a4 node::Start(int, char**) [/Users/morgante/.nvm/versions/node/v18.20.0/bin/node]
13: 0x1859250e0 start [/usr/lib/dyld]
[1] 48713 abort node ./examples/node.mjs
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at napi::threadsafe_function::ThreadsafeFunction::call_async and the threadsafe_function.rs:749 failure shown in the stack trace, then reproduce the supplied Rust and JavaScript example. Done means an error thrown by the JavaScript callback is represented through the returned Result without aborting the Node.js process.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js, rust
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100