summaryrefslogtreecommitdiff
path: root/src/util.rs
diff options
context:
space:
mode:
authorkyren <kerriganw@gmail.com>2017-06-25 01:10:26 -0400
committerkyren <kerriganw@gmail.com>2017-06-25 01:10:26 -0400
commita609f709eef528faa856c43ed1766ec576087130 (patch)
treeb972a453a0ab9f99a55f6f579027ae9a1ebea5e7 /src/util.rs
parentb59b8cc23bd2ce510c754bdede5095ffd7904dcf (diff)
downloadmlua-a609f709eef528faa856c43ed1766ec576087130.zip
A lot of corner case bugfixes
Diffstat (limited to 'src/util.rs')
-rw-r--r--src/util.rs40
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!(