diff --git a/src/hook.rs b/src/hook.rs index dd9b5c6..ba2e507 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -3,9 +3,8 @@ use std::ffi::CStr; use std::ops::{BitOr, BitOrAssign}; use std::os::raw::{c_char, c_int}; -use crate::ffi::{self, lua_Debug, lua_State}; +use crate::ffi::{self, lua_Debug}; use crate::lua::Lua; -use crate::util::callback_error; /// Contains information about currently executing Lua code. /// @@ -283,22 +282,6 @@ impl BitOrAssign for HookTriggers { } } -pub(crate) unsafe extern "C" fn hook_proc(state: *mut lua_State, ar: *mut lua_Debug) { - callback_error(state, |_| { - let lua = mlua_expect!(Lua::make_from_ptr(state), "cannot make Lua instance"); - let debug = Debug::new(&lua, ar); - let hook_cb = mlua_expect!(lua.hook_callback(), "no hook callback set in hook_proc"); - - #[allow(clippy::match_wild_err_arm)] - match hook_cb.try_borrow_mut() { - Ok(mut b) => (&mut *b)(&lua, debug), - Err(_) => mlua_panic!("Lua should not allow hooks to be called within another hook"), - }?; - - Ok(()) - }) -} - unsafe fn ptr_to_str<'a>(input: *const c_char) -> Option<&'a [u8]> { if input.is_null() { None diff --git a/src/lua.rs b/src/lua.rs index 7d8b0eb..f5d4350 100644 --- a/src/lua.rs +++ b/src/lua.rs @@ -14,7 +14,7 @@ use rustc_hash::FxHashMap; use crate::error::{Error, Result}; use crate::ffi; use crate::function::Function; -use crate::hook::{hook_proc, Debug, HookTriggers}; +use crate::hook::{Debug, HookTriggers}; use crate::scope::Scope; use crate::stdlib::StdLib; use crate::string::String; @@ -765,9 +765,32 @@ impl Lua { where F: 'static + MaybeSend + FnMut(&Lua, Debug) -> Result<()>, { + unsafe extern "C" fn hook_proc(state: *mut ffi::lua_State, ar: *mut ffi::lua_Debug) { + let lua = match Lua::make_from_ptr(state) { + Some(lua) => lua, + None => return, + }; + let extra = lua.extra.get(); + callback_error_ext(state, extra, move |_| { + let debug = Debug::new(&lua, ar); + let hook_cb = (*lua.extra.get()).hook_callback.clone(); + let hook_cb = mlua_expect!(hook_cb, "no hook callback set in hook_proc"); + + #[allow(clippy::match_wild_err_arm)] + match hook_cb.try_lock() { + Ok(mut cb) => cb(&lua, debug), + Err(_) => { + mlua_panic!("Lua should not allow hooks to be called within another hook") + } + }?; + + Ok(()) + }) + } + let state = self.main_state.ok_or(Error::MainThreadNotAvailable)?; unsafe { - (*self.extra.get()).hook_callback = Some(Arc::new(RefCell::new(callback))); + (*self.extra.get()).hook_callback = Some(Arc::new(Mutex::new(callback))); ffi::lua_sethook(state, Some(hook_proc), triggers.mask(), triggers.count()); } Ok(()) @@ -805,7 +828,7 @@ impl Lua { callback_error_ext(state, extra, move |_| { let cb = mlua_expect!( (*lua.extra.get()).warn_callback.as_ref(), - "no warning callback set" + "no warning callback set in warn_proc" ); let msg = CStr::from_ptr(msg); cb(&lua, msg, tocont != 0) @@ -2468,10 +2491,6 @@ impl Lua { }) } - pub(crate) unsafe fn hook_callback(&self) -> Option { - (*self.extra.get()).hook_callback.clone() - } - #[inline] pub(crate) fn new_or_cached_multivalue(&self) -> MultiValue { unsafe { diff --git a/src/types.rs b/src/types.rs index 0f07e8c..cd4b13f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,4 +1,3 @@ -use std::cell::RefCell; use std::hash::{Hash, Hasher}; use std::os::raw::{c_int, c_void}; use std::sync::{Arc, Mutex}; @@ -51,10 +50,10 @@ pub(crate) struct AsyncPollUpvalue<'lua> { } #[cfg(feature = "send")] -pub(crate) type HookCallback = Arc Result<()> + Send>>; +pub(crate) type HookCallback = Arc Result<()> + Send>>; #[cfg(not(feature = "send"))] -pub(crate) type HookCallback = Arc Result<()>>>; +pub(crate) type HookCallback = Arc Result<()>>>; #[cfg(all(feature = "send", feature = "lua54"))] pub(crate) type WarnCallback = Box Result<()> + Send>;