Skip to content

Commit e51ff8f

Browse files
committed
Use a mutex for runtime.
1 parent cd6cdb6 commit e51ff8f

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

rs/libmoq/src/ffi.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{
22
ffi::{c_char, c_void},
3-
sync::LazyLock,
3+
sync::{LazyLock, Mutex},
44
};
55

66
use url::Url;
77

88
use crate::{Error, Id};
99

10-
pub static RUNTIME: LazyLock<tokio::runtime::Handle> = LazyLock::new(|| {
10+
pub static RUNTIME: LazyLock<Mutex<tokio::runtime::Handle>> = LazyLock::new(|| {
1111
let runtime = tokio::runtime::Builder::new_current_thread()
1212
.enable_all()
1313
.build()
@@ -21,15 +21,20 @@ pub static RUNTIME: LazyLock<tokio::runtime::Handle> = LazyLock::new(|| {
2121
})
2222
.expect("failed to spawn runtime thread");
2323

24-
handle
24+
Mutex::new(handle)
2525
});
2626

27-
/// Runs the provided function while holding the global state and runtime lock.
27+
/// Runs the provided function in the runtime context.
2828
/// Additionally, we convert the return code to a C-compatible return value.
29+
///
30+
/// Uses a mutex to ensure Handle::enter() guards are dropped in LIFO order,
31+
/// as required by tokio to avoid panics in multi-threaded FFI contexts.
2932
pub fn enter<C: ReturnCode, F: FnOnce() -> C>(f: F) -> i32 {
30-
// TODO Do we need a mutex to make sure RUNTIME is dropped in order?
31-
// I think this might panic otherwise if libmoq is used in a multi-threaded context.
32-
let _guard = RUNTIME.enter();
33+
// NOTE: I think we need a mutex because Handle::enter() needs to be dropped in LIFO order.
34+
// If this starts to become a bottleneck, we might have to rethink our runtime model.
35+
let handle = RUNTIME.lock().unwrap();
36+
let _guard = handle.enter();
37+
3338
match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
3439
Ok(ret) => ret.code(),
3540
Err(_) => Error::Panic.code(),

0 commit comments

Comments
 (0)