Skip to content

Commit 3dd9143

Browse files
authored
fix(napi): re-create async runtime (#2519)
1 parent 574e7e4 commit 3dd9143

File tree

3 files changed

+23
-11
lines changed

3 files changed

+23
-11
lines changed

crates/napi/src/bindgen_runtime/module_register.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ pub unsafe extern "C" fn napi_register_module_v1(
480480
create_custom_gc(env, current_thread_id);
481481
#[cfg(feature = "tokio_rt")]
482482
{
483-
crate::tokio_runtime::ensure_runtime();
483+
crate::tokio_runtime::start_async_runtime();
484484
}
485485
}
486486
FIRST_MODULE_REGISTERED.store(true, Ordering::SeqCst);
@@ -570,7 +570,7 @@ unsafe extern "C" fn thread_cleanup(
570570
if MODULE_COUNT.fetch_sub(1, Ordering::Relaxed) == 1 {
571571
#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
572572
{
573-
crate::tokio_runtime::shutdown_tokio_runtime();
573+
crate::tokio_runtime::shutdown_async_runtime();
574574
}
575575
crate::bindgen_runtime::REFERENCE_MAP.borrow_mut(|m| m.clear());
576576
#[allow(clippy::needless_return)]

crates/napi/src/tokio_runtime.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ use crate::{JsDeferred, JsUnknown, NapiValue};
1010

1111
#[cfg(not(feature = "noop"))]
1212
fn create_runtime() -> Runtime {
13+
if let Some(user_defined_rt) = USER_DEFINED_RT
14+
.get()
15+
.and_then(|rt| rt.write().ok().and_then(|mut rt| rt.take()))
16+
{
17+
return user_defined_rt;
18+
}
1319
#[cfg(any(
1420
all(target_family = "wasm", tokio_unstable),
1521
not(target_family = "wasm")
@@ -57,19 +63,25 @@ pub fn create_custom_tokio_runtime(rt: Runtime) {
5763
pub fn create_custom_tokio_runtime(_: Runtime) {}
5864

5965
#[cfg(not(feature = "noop"))]
60-
/// Ensure that the Tokio runtime is initialized.
61-
/// In Node.js the Tokio runtime will be dropped when Node env exits.
66+
/// Start the async runtime (Currently is tokio).
67+
///
68+
/// In Node.js native targets the async runtime will be dropped when Node env exits.
6269
/// But in Electron renderer process, the Node env will exits and recreate when the window reloads.
63-
/// So we need to ensure that the Tokio runtime is initialized when the Node env is created.
64-
pub(crate) fn ensure_runtime() {
65-
let mut rt = RT.write().unwrap();
66-
if rt.is_none() {
67-
*rt = Some(create_runtime());
70+
/// So we need to ensure that the async runtime is initialized when the Node env is created.
71+
///
72+
/// In wasm targets, the async runtime will not been shutdown automatically due to the limitation of the wasm runtime.
73+
/// So, you need to call `shutdown_async_runtime` function to manually shutdown the async runtime.
74+
/// In some scenarios, you may want to start the async runtime again like in tests.
75+
pub fn start_async_runtime() {
76+
if let Ok(mut rt) = RT.write() {
77+
if rt.is_none() {
78+
*rt = Some(create_runtime());
79+
}
6880
}
6981
}
7082

7183
#[cfg(not(feature = "noop"))]
72-
pub fn shutdown_tokio_runtime() {
84+
pub fn shutdown_async_runtime() {
7385
if let Some(rt) = RT.write().ok().and_then(|mut rt| rt.take()) {
7486
rt.shutdown_background();
7587
}

examples/napi/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub const TYPE_SKIPPED_CONST: u32 = 12;
4444
pub fn shutdown_runtime() {
4545
#[cfg(all(target_family = "wasm", tokio_unstable))]
4646
{
47-
napi::bindgen_prelude::shutdown_tokio_runtime();
47+
napi::bindgen_prelude::shutdown_async_runtime();
4848
}
4949
}
5050

0 commit comments

Comments
 (0)