diff options
author | Alex Orlenko <zxteam@protonmail.com> | 2022-04-08 10:45:28 +0100 |
---|---|---|
committer | Alex Orlenko <zxteam@protonmail.com> | 2022-04-08 10:45:28 +0100 |
commit | 70d287cf9f389f1a8f318ff201dd54b575a9f5b2 (patch) | |
tree | 3faecabccaa64ff7c2616d1522f81a4aa1553cfc /src | |
parent | d607039a313b77dd6db1e2e3cd0643a09c652f86 (diff) | |
download | mlua-70d287cf9f389f1a8f318ff201dd54b575a9f5b2.zip |
Don't pass Lua handler to interrupt callback (Luau) as it's not safe.
Optimize callback_error_ext to check stack only before allocating a new WrappedFailure.
Diffstat (limited to 'src')
-rw-r--r-- | src/lua.rs | 30 | ||||
-rw-r--r-- | src/types.rs | 4 |
2 files changed, 15 insertions, 19 deletions
@@ -934,7 +934,7 @@ impl Lua { /// # fn main() -> Result<()> { /// let lua = Lua::new(); /// let count = Arc::new(AtomicU64::new(0)); - /// lua.set_interrupt(move |_lua| { + /// lua.set_interrupt(move || { /// if count.fetch_add(1, Ordering::Relaxed) % 2 == 0 { /// return Ok(VmState::Yield); /// } @@ -958,19 +958,17 @@ impl Lua { #[cfg_attr(docsrs, doc(cfg(feature = "luau")))] pub fn set_interrupt<F>(&self, callback: F) where - F: 'static + MaybeSend + Fn(&Lua) -> Result<VmState>, + F: 'static + MaybeSend + Fn() -> Result<VmState>, { unsafe extern "C" fn interrupt_proc(state: *mut ffi::lua_State, gc: c_int) { - if gc != -1 { + if gc >= 0 { // We don't support GC interrupts since they cannot survive Lua exceptions return; } - // TODO: think about not using drop types here - let lua = match Lua::make_from_ptr(state) { - Some(lua) => lua, + let extra = match extra_data(state) { + Some(e) => e.get(), None => return, }; - let extra = lua.extra.get(); let result = callback_error_ext(state, extra, move |_| { let interrupt_cb = (*extra).interrupt_callback.clone(); let interrupt_cb = @@ -978,7 +976,7 @@ impl Lua { if Arc::strong_count(&interrupt_cb) > 2 { return Ok(VmState::Continue); // Don't allow recursion } - interrupt_cb(&lua) + interrupt_cb() }); match result { VmState::Continue => {} @@ -2855,7 +2853,6 @@ pub(crate) fn init_metatable_cache(cache: &mut FxHashMap<TypeId, u8>) { // An optimized version of `callback_error` that does not allocate `WrappedFailure` userdata // and instead reuses unsed and cached values from previous calls (or allocates new). -// It requires `get_extra` function to return `ExtraData` value. unsafe fn callback_error_ext<F, R>(state: *mut ffi::lua_State, extra: *mut ExtraData, f: F) -> R where F: FnOnce(c_int) -> Result<R>, @@ -2867,14 +2864,6 @@ where let nargs = ffi::lua_gettop(state); - // We need 2 extra stack spaces to store preallocated memory and error/panic metatable. - let extra_stack = if nargs < 2 { 2 - nargs } else { 1 }; - ffi::luaL_checkstack( - state, - extra_stack, - cstr!("not enough stack space for callback error handling"), - ); - enum PreallocatedFailure { New(*mut WrappedFailure), Cached(i32), @@ -2885,6 +2874,13 @@ where let prealloc_failure = match extra.wrapped_failures_cache.pop() { Some(index) => PreallocatedFailure::Cached(index), None => { + // We need 2 extra stack spaces to store userdata and error/panic metatable. + let extra_stack = if nargs < 2 { 2 - nargs } else { 1 }; + ffi::luaL_checkstack( + state, + extra_stack, + cstr!("not enough stack space for callback error handling"), + ); let ud = WrappedFailure::new_userdata(state); ffi::lua_rotate(state, 1, 1); PreallocatedFailure::New(ud) diff --git a/src/types.rs b/src/types.rs index 47d6de3..a14ff3f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -65,10 +65,10 @@ pub(crate) type HookCallback = Arc<dyn Fn(&Lua, Debug) -> Result<()> + Send>; pub(crate) type HookCallback = Arc<dyn Fn(&Lua, Debug) -> Result<()>>; #[cfg(all(feature = "luau", feature = "send"))] -pub(crate) type InterruptCallback = Arc<dyn Fn(&Lua) -> Result<VmState> + Send>; +pub(crate) type InterruptCallback = Arc<dyn Fn() -> Result<VmState> + Send>; #[cfg(all(feature = "luau", not(feature = "send")))] -pub(crate) type InterruptCallback = Arc<dyn Fn(&Lua) -> Result<VmState>>; +pub(crate) type InterruptCallback = Arc<dyn Fn() -> Result<VmState>>; #[cfg(all(feature = "send", feature = "lua54"))] pub(crate) type WarnCallback = Box<dyn Fn(&Lua, &CStr, bool) -> Result<()> + Send>; |