diff options
author | kyren <kerriganw@gmail.com> | 2017-06-25 01:10:26 -0400 |
---|---|---|
committer | kyren <kerriganw@gmail.com> | 2017-06-25 01:10:26 -0400 |
commit | a609f709eef528faa856c43ed1766ec576087130 (patch) | |
tree | b972a453a0ab9f99a55f6f579027ae9a1ebea5e7 /src/util.rs | |
parent | b59b8cc23bd2ce510c754bdede5095ffd7904dcf (diff) | |
download | mlua-a609f709eef528faa856c43ed1766ec576087130.zip |
A lot of corner case bugfixes
Diffstat (limited to 'src/util.rs')
-rw-r--r-- | src/util.rs | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/src/util.rs b/src/util.rs index d043248..32161c0 100644 --- a/src/util.rs +++ b/src/util.rs @@ -113,11 +113,10 @@ where } // If the return code indicates an error, pops the error off of the stack and -// returns Err. If the error was actually a rust panic, clears the current lua -// stack and panics. If the error on the top of the stack is actually a -// WrappedError::Error, just returns it. If the error on the top of the stack -// is a WrappedError::Panic, clears the rust stack and resumes the panic, -// otherwise interprets the error as the appropriate lua error. +// returns Err. If the error is actually a WrappedPaic, clears the current lua +// stack continues the panic. If the error on the top of the stack is actually +// a WrappedError, just returns it. Otherwise, interprets the error as the +// appropriate lua error. pub unsafe fn handle_error(state: *mut ffi::lua_State, err: c_int) -> LuaResult<()> { if err == ffi::LUA_OK || err == ffi::LUA_YIELD { Ok(()) @@ -126,12 +125,19 @@ pub unsafe fn handle_error(state: *mut ffi::lua_State, err: c_int) -> LuaResult< Err(pop_wrapped_error(state).unwrap()) } else if is_wrapped_panic(state, -1) { - resume_unwind(pop_wrapped_panic(state).unwrap()) + let userdata = ffi::lua_touserdata(state, -1); + let panic = &mut *(userdata as *mut WrappedPanic); + resume_unwind(panic.0.take().expect( + "internal error: panic was resumed twice", + )) } else { let err_string = if let Some(s) = ffi::lua_tolstring(state, -1, ptr::null_mut()).as_ref() { - CStr::from_ptr(s).to_str().unwrap().to_owned() + CStr::from_ptr(s) + .to_str() + .unwrap_or_else(|_| "<unprintable error>") + .to_owned() } else { "<unprintable error>".to_owned() }; @@ -227,7 +233,7 @@ pub unsafe fn pcall_with_traceback( ffi::luaL_traceback(state, state, ptr::null(), 0); let traceback = CStr::from_ptr(ffi::lua_tolstring(state, -1, ptr::null_mut())) .to_str() - .unwrap() + .unwrap_or_else(|_| "<could not capture traceback>") .to_owned(); push_wrapped_error(state, LuaError::CallbackError(traceback, Arc::new(error))); } else if !is_wrapped_panic(state, 1) { @@ -261,7 +267,7 @@ pub unsafe fn resume_with_traceback( ffi::luaL_traceback(from, state, ptr::null(), 0); let traceback = CStr::from_ptr(ffi::lua_tolstring(from, -1, ptr::null_mut())) .to_str() - .unwrap() + .unwrap_or_else(|_| "<could not capture traceback>") .to_owned(); push_wrapped_error(from, LuaError::CallbackError(traceback, Arc::new(error))); } else if !is_wrapped_panic(state, 1) { @@ -321,8 +327,8 @@ pub unsafe fn main_state(state: *mut ffi::lua_State) -> *mut ffi::lua_State { state } -pub struct WrappedError(LuaError); -pub struct WrappedPanic(Option<Box<Any + Send>>); +pub struct WrappedError(pub LuaError); +pub struct WrappedPanic(pub Option<Box<Any + Send>>); // Pushes a WrappedError::Error to the top of the stack pub unsafe fn push_wrapped_error(state: *mut ffi::lua_State, err: LuaError) { @@ -427,18 +433,6 @@ pub unsafe fn pop_wrapped_error(state: *mut ffi::lua_State) -> Option<LuaError> } } -// Pops a WrappedError off of the top of the stack, if it is a WrappedError. If -// it is not a WrappedError, returns None and does not pop anything. -pub unsafe fn pop_wrapped_panic(state: *mut ffi::lua_State) -> Option<Box<Any + Send>> { - if ffi::lua_gettop(state) == 0 || !is_wrapped_panic(state, -1) { - None - } else { - let userdata = ffi::lua_touserdata(state, -1); - let panic = &mut *(userdata as *mut WrappedPanic); - panic.0.take() - } -} - // Checks if the value at the given index is a WrappedError pub unsafe fn is_wrapped_error(state: *mut ffi::lua_State, index: c_int) -> bool { assert_ne!( |