fix(napi): segfault when ThreadsafeFunction
's callback closure captures data (#1281)
This commit is contained in:
parent
b7a3103f0c
commit
99e17c7294
6 changed files with 32 additions and 5 deletions
|
@ -214,9 +214,9 @@ impl<T: 'static, ES: ErrorStrategy::T> ThreadsafeFunction<T, ES> {
|
|||
async_resource_name,
|
||||
max_queue_size,
|
||||
initial_thread_count,
|
||||
ptr,
|
||||
Some(thread_finalize_cb::<T, V, R>),
|
||||
aborted_ptr as *mut c_void,
|
||||
Some(thread_finalize_cb::<T, V, R>),
|
||||
ptr,
|
||||
Some(call_js_cb::<T, V, R, ES>),
|
||||
&mut raw_tsfn,
|
||||
)
|
||||
|
@ -355,8 +355,8 @@ unsafe extern "C" fn thread_finalize_cb<T: 'static, V: ToNapiValue, R>(
|
|||
R: 'static + Send + FnMut(ThreadSafeCallContext<T>) -> Result<Vec<V>>,
|
||||
{
|
||||
// cleanup
|
||||
drop(unsafe { Box::<R>::from_raw(finalize_data.cast()) });
|
||||
let aborted = unsafe { Arc::<Mutex<bool>>::from_raw(finalize_hint.cast()) };
|
||||
drop(unsafe { Box::<R>::from_raw(finalize_hint.cast()) });
|
||||
let aborted = unsafe { Arc::<Mutex<bool>>::from_raw(finalize_data.cast()) };
|
||||
let mut is_aborted = aborted.lock().unwrap();
|
||||
*is_aborted = true;
|
||||
}
|
||||
|
|
|
@ -193,6 +193,7 @@ Generated by [AVA](https://avajs.dev).
|
|||
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void␊
|
||||
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void␊
|
||||
export function threadsafeFunctionFatalModeError(cb: (...args: any[]) => any): void␊
|
||||
export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void␊
|
||||
export function useTokioWithoutAsync(): void␊
|
||||
export function getBuffer(): Buffer␊
|
||||
export function appendBuffer(buf: Buffer): Buffer␊
|
||||
|
|
Binary file not shown.
|
@ -50,6 +50,7 @@ import {
|
|||
bigintGetU64AsString,
|
||||
callThreadsafeFunction,
|
||||
threadsafeFunctionThrowError,
|
||||
threadsafeFunctionClosureCapture,
|
||||
asyncPlus100,
|
||||
getGlobal,
|
||||
getUndefined,
|
||||
|
@ -691,6 +692,15 @@ Napi4Test('throw error from thread safe function', async (t) => {
|
|||
t.is(err!.message, 'ThrowFromNative')
|
||||
})
|
||||
|
||||
Napi4Test('thread safe function closure capture data', (t) => {
|
||||
return new Promise((resolve) => {
|
||||
threadsafeFunctionClosureCapture(() => {
|
||||
resolve()
|
||||
t.pass()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Napi4Test('resolve value from thread safe function fatal mode', async (t) => {
|
||||
const tsfnFatalMode = new Promise<boolean>((resolve) => {
|
||||
threadsafeFunctionFatalMode(resolve)
|
||||
|
|
1
examples/napi/index.d.ts
vendored
1
examples/napi/index.d.ts
vendored
|
@ -183,6 +183,7 @@ export function callThreadsafeFunction(callback: (...args: any[]) => any): void
|
|||
export function threadsafeFunctionThrowError(cb: (...args: any[]) => any): void
|
||||
export function threadsafeFunctionFatalMode(cb: (...args: any[]) => any): void
|
||||
export function threadsafeFunctionFatalModeError(cb: (...args: any[]) => any): void
|
||||
export function threadsafeFunctionClosureCapture(func: (...args: any[]) => any): void
|
||||
export function useTokioWithoutAsync(): void
|
||||
export function getBuffer(): Buffer
|
||||
export function appendBuffer(buf: Buffer): Buffer
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::thread;
|
|||
use napi::{
|
||||
bindgen_prelude::*,
|
||||
threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode},
|
||||
JsBoolean,
|
||||
JsBoolean, JsString,
|
||||
};
|
||||
|
||||
#[napi]
|
||||
|
@ -61,3 +61,18 @@ pub fn threadsafe_function_fatal_mode_error(cb: JsFunction) -> Result<()> {
|
|||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn threadsafe_function_closure_capture(func: JsFunction) -> napi::Result<()> {
|
||||
let str = "test";
|
||||
let tsfn: ThreadsafeFunction<()> = func
|
||||
.create_threadsafe_function(0, move |_| {
|
||||
println!("{}", str); // str is NULL at this point
|
||||
Ok(Vec::<JsString>::new())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
tsfn.call(Ok(()), ThreadsafeFunctionCallMode::NonBlocking);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue