From 5b5f616d81ff2f0e154ff8b1e1edee1dfc087eb4 Mon Sep 17 00:00:00 2001 From: Louis Date: Thu, 22 Feb 2024 10:34:10 +0100 Subject: [PATCH] fix(napi): no hard fail on ThreadsafeFunction::call_async (#1970) For many reasons, in an app we can end up in a scenario where the thread / task that initially called the ThreadsafeFunction gets interrupted. This means that the receiver would get collected, should a ThreadsafeFunction be awaited on the said thread. This will create an error when the ThreadsafeFunction's callback will be called, and call a napi_fatal_error. This change makes it so that if the send errors, this error is hidden and thus prevents any hard failure. If a ThreadsafeFunction is called in such a case, its output won't be used, but we'll still run all the logic to ensure it ran properly. Fixes https://github.com/napi-rs/napi-rs/issues/1665 - cc @Brooooooklyn --- crates/napi/src/threadsafe_function.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/napi/src/threadsafe_function.rs b/crates/napi/src/threadsafe_function.rs index 45504079..41df54d4 100644 --- a/crates/napi/src/threadsafe_function.rs +++ b/crates/napi/src/threadsafe_function.rs @@ -494,9 +494,9 @@ impl ThreadsafeFunction { callback: Box::new(move |d: Result| { sender .send(d.and_then(|d| D::from_napi_value(d.0.env, d.0.value))) - .map_err(|_| { - crate::Error::from_reason("Failed to send return value to tokio sender") - }) + // The only reason for send to return Err is if the receiver isn't listening + // Not hiding the error would result in a napi_fatal_error call, it's safe to ignore it instead. + .or(Ok(())) }), } }))) @@ -591,9 +591,11 @@ impl ThreadsafeFunction { callback: Box::new(move |d: Result| { d.and_then(|d| { D::from_napi_value(d.0.env, d.0.value).and_then(move |d| { - sender.send(d).map_err(|_| { - crate::Error::from_reason("Failed to send return value to tokio sender") - }) + sender + .send(d) + // The only reason for send to return Err is if the receiver isn't listening + // Not hiding the error would result in a napi_fatal_error call, it's safe to ignore it instead. + .or(Ok(())) }) }) }),