Skip to content

Commit 825bdbf

Browse files
committed
Use dynamic Lua state ownership instead of compile-time module cfg flag to allow
creating new VMs in module mode (and destructing them properly).
1 parent 1634c43 commit 825bdbf

File tree

8 files changed

+43
-17
lines changed

8 files changed

+43
-17
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ $ lua5.4 -e 'require("my_module").hello("world")'
195195
hello, world!
196196
```
197197

198-
On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config` with the following content:
198+
On macOS, you need to set additional linker arguments. One option is to compile with `cargo rustc --release -- -C link-arg=-undefined -C link-arg=dynamic_lookup`, the other is to create a `.cargo/config.toml` with the following content:
199199
``` toml
200200
[target.x86_64-apple-darwin]
201201
rustflags = [

src/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ impl Lua {
271271
#[inline]
272272
pub unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> Lua {
273273
Lua {
274-
raw: RawLua::init_from_ptr(state),
274+
raw: RawLua::init_from_ptr(state, false),
275275
collect_garbage: true,
276276
}
277277
}

src/state/extra.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const REF_STACK_RESERVE: c_int = 1;
3333
pub(crate) struct ExtraData {
3434
pub(super) lua: MaybeUninit<Lua>,
3535
pub(super) weak: MaybeUninit<WeakLua>,
36+
pub(super) owned: bool,
3637

3738
pub(super) registered_userdata: FxHashMap<TypeId, c_int>,
3839
pub(super) registered_userdata_mt: FxHashMap<*const c_void, Option<TypeId>>,
@@ -46,7 +47,7 @@ pub(crate) struct ExtraData {
4647

4748
pub(super) safe: bool,
4849
pub(super) libs: StdLib,
49-
#[cfg(feature = "module")]
50+
// Used in module mode
5051
pub(super) skip_memory_check: bool,
5152

5253
// Auxiliary thread to store references
@@ -88,8 +89,9 @@ pub(crate) struct ExtraData {
8889
impl Drop for ExtraData {
8990
fn drop(&mut self) {
9091
unsafe {
91-
#[cfg(feature = "module")]
92-
self.lua.assume_init_drop();
92+
if !self.owned {
93+
self.lua.assume_init_drop();
94+
}
9395

9496
self.weak.assume_init_drop();
9597
}
@@ -111,7 +113,7 @@ impl ExtraData {
111113
#[cfg(any(feature = "lua51", feature = "luajit", feature = "luau"))]
112114
pub(super) const ERROR_TRACEBACK_IDX: c_int = 1;
113115

114-
pub(super) unsafe fn init(state: *mut ffi::lua_State) -> XRc<UnsafeCell<Self>> {
116+
pub(super) unsafe fn init(state: *mut ffi::lua_State, owned: bool) -> XRc<UnsafeCell<Self>> {
115117
// Create ref stack thread and place it in the registry to prevent it
116118
// from being garbage collected.
117119
let ref_thread = mlua_expect!(
@@ -141,14 +143,14 @@ impl ExtraData {
141143
let extra = XRc::new(UnsafeCell::new(ExtraData {
142144
lua: MaybeUninit::uninit(),
143145
weak: MaybeUninit::uninit(),
146+
owned,
144147
registered_userdata: FxHashMap::default(),
145148
registered_userdata_mt: FxHashMap::default(),
146149
last_checked_userdata_mt: (ptr::null(), None),
147150
registry_unref_list: Arc::new(Mutex::new(Some(Vec::new()))),
148151
app_data: AppData::default(),
149152
safe: false,
150153
libs: StdLib::NONE,
151-
#[cfg(feature = "module")]
152154
skip_memory_check: false,
153155
ref_thread,
154156
// We need some reserved stack space to move values in and out of the ref stack.
@@ -188,7 +190,7 @@ impl ExtraData {
188190
raw: XRc::clone(raw),
189191
collect_garbage: false,
190192
});
191-
if cfg!(not(feature = "module")) {
193+
if self.owned {
192194
XRc::decrement_strong_count(XRc::as_ptr(raw));
193195
}
194196
self.weak.write(WeakLua(XRc::downgrade(raw)));

src/state/raw.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ pub struct RawLua {
5050
pub(super) extra: XRc<UnsafeCell<ExtraData>>,
5151
}
5252

53-
#[cfg(not(feature = "module"))]
5453
impl Drop for RawLua {
5554
fn drop(&mut self) {
5655
unsafe {
56+
if !(*self.extra.get()).owned {
57+
return;
58+
}
59+
5760
let mem_state = MemoryState::get(self.main_state);
5861

5962
ffi::lua_close(self.main_state);
@@ -115,7 +118,7 @@ impl RawLua {
115118
ffi::luau_codegen_create(state);
116119
}
117120

118-
let rawlua = Self::init_from_ptr(state);
121+
let rawlua = Self::init_from_ptr(state, true);
119122
let extra = rawlua.lock().extra.get();
120123

121124
mlua_expect!(
@@ -154,7 +157,7 @@ impl RawLua {
154157
rawlua
155158
}
156159

157-
pub(super) unsafe fn init_from_ptr(state: *mut ffi::lua_State) -> XRc<ReentrantMutex<Self>> {
160+
pub(super) unsafe fn init_from_ptr(state: *mut ffi::lua_State, owned: bool) -> XRc<ReentrantMutex<Self>> {
158161
assert!(!state.is_null(), "Lua state is NULL");
159162
if let Some(lua) = Self::try_from_ptr(state) {
160163
return lua;
@@ -191,7 +194,7 @@ impl RawLua {
191194
);
192195

193196
// Init ExtraData
194-
let extra = ExtraData::init(main_state);
197+
let extra = ExtraData::init(main_state, owned);
195198

196199
// Register `DestructedUserdata` type
197200
get_destructed_userdata_metatable(main_state);
@@ -704,10 +707,7 @@ impl RawLua {
704707
// MemoryInfo is empty in module mode so we cannot predict memory limits
705708
match MemoryState::get(self.main_state) {
706709
mem_state if !mem_state.is_null() => (*mem_state).memory_limit() == 0,
707-
#[cfg(feature = "module")]
708710
_ => (*self.extra.get()).skip_memory_check, // Check the special flag (only for module mode)
709-
#[cfg(not(feature = "module"))]
710-
_ => false,
711711
}
712712
}
713713

tests/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ fn test_c_function() -> Result<()> {
8484
let lua = Lua::new();
8585

8686
unsafe extern "C-unwind" fn c_function(state: *mut mlua::lua_State) -> std::os::raw::c_int {
87-
let lua = Lua::init_from_ptr(state);
88-
lua.globals().set("c_function", true).unwrap();
87+
ffi::lua_pushboolean(state, 1);
88+
ffi::lua_setglobal(state, b"c_function\0" as *const _ as *const _);
8989
0
9090
}
9191

File renamed without changes.

tests/module/loader/tests/load.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ fn test_module_multi_from_thread() -> Result<()> {
9292
.exec()
9393
}
9494

95+
#[test]
96+
fn test_module_new_vm() -> Result<()> {
97+
let lua = make_lua()?;
98+
lua.load(
99+
r#"
100+
local mod = require("test_module.new_vm")
101+
assert(mod.eval("return \"hello, world\"") == "hello, world")
102+
"#,
103+
)
104+
.exec()
105+
}
106+
95107
fn make_lua() -> Result<Lua> {
96108
let (dylib_path, dylib_ext, separator);
97109
if cfg!(target_os = "macos") {

tests/module/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ fn test_module2(lua: &Lua) -> LuaResult<LuaTable> {
3333
Ok(exports)
3434
}
3535

36+
#[mlua::lua_module]
37+
fn test_module_new_vm(lua: &Lua) -> LuaResult<LuaTable> {
38+
let eval = lua.create_function(|_, prog: String| {
39+
let lua = Lua::new();
40+
lua.load(prog).eval::<Option<String>>()
41+
})?;
42+
43+
let exports = lua.create_table()?;
44+
exports.set("eval", eval)?;
45+
Ok(exports)
46+
}
47+
3648
#[mlua::lua_module]
3749
fn test_module_error(_: &Lua) -> LuaResult<LuaTable> {
3850
Err("custom module error".into_lua_err())

0 commit comments

Comments
 (0)