Fix several bugs with error handling in xxx_with_traceback functions
In resume_with_traceback, always use the coroutine stack for error handling so we don't miss panics, in both _with_traceback functions remove the temporary traceback entry from the stack.
This commit is contained in:
parent
a2b77f37a2
commit
d415455ccb
|
@ -858,7 +858,7 @@ impl<'lua> Thread<'lua> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_error(
|
handle_error(
|
||||||
lua.state,
|
thread_state,
|
||||||
resume_with_traceback(thread_state, lua.state, nargs),
|
resume_with_traceback(thread_state, lua.state, nargs),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
14
src/tests.rs
14
src/tests.rs
|
@ -893,3 +893,17 @@ fn coroutine_from_closure() {
|
||||||
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
let thrd: Thread = lua.eval("coroutine.create(main)", None).unwrap();
|
||||||
thrd.resume::<_, ()>(()).unwrap();
|
thrd.resume::<_, ()>(()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn coroutine_panic() {
|
||||||
|
let lua = Lua::new();
|
||||||
|
let thrd_main = lua.create_function(|lua, _| {
|
||||||
|
// whoops, 'main' has a wrong type
|
||||||
|
let _coro: u32 = lua.globals().get("main").unwrap();
|
||||||
|
lua.pack(())
|
||||||
|
});
|
||||||
|
lua.globals().set("main", thrd_main.clone()).unwrap();
|
||||||
|
let thrd: Thread = lua.create_thread(thrd_main);
|
||||||
|
thrd.resume::<_, ()>(()).unwrap();
|
||||||
|
}
|
||||||
|
|
14
src/util.rs
14
src/util.rs
|
@ -381,6 +381,7 @@ pub unsafe fn pcall_with_traceback(
|
||||||
.unwrap_or_else(|_| "<could not capture traceback>")
|
.unwrap_or_else(|_| "<could not capture traceback>")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
push_wrapped_error(state, Error::CallbackError(traceback, Arc::new(error)));
|
push_wrapped_error(state, Error::CallbackError(traceback, Arc::new(error)));
|
||||||
|
ffi::lua_remove(state, -2);
|
||||||
} else if !is_wrapped_panic(state, 1) {
|
} else if !is_wrapped_panic(state, 1) {
|
||||||
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
||||||
if !s.is_null() {
|
if !s.is_null() {
|
||||||
|
@ -388,6 +389,7 @@ pub unsafe fn pcall_with_traceback(
|
||||||
} else {
|
} else {
|
||||||
ffi::luaL_traceback(state, state, cstr!("<unprintable lua error>"), 0);
|
ffi::luaL_traceback(state, state, cstr!("<unprintable lua error>"), 0);
|
||||||
}
|
}
|
||||||
|
ffi::lua_remove(state, -2);
|
||||||
}
|
}
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
@ -408,19 +410,21 @@ pub unsafe fn resume_with_traceback(
|
||||||
let res = ffi::lua_resume(state, from, nargs);
|
let res = ffi::lua_resume(state, from, nargs);
|
||||||
if res != ffi::LUA_OK && res != ffi::LUA_YIELD {
|
if res != ffi::LUA_OK && res != ffi::LUA_YIELD {
|
||||||
if let Some(error) = pop_wrapped_error(state) {
|
if let Some(error) = pop_wrapped_error(state) {
|
||||||
ffi::luaL_traceback(from, state, ptr::null(), 0);
|
ffi::luaL_traceback(state, state, ptr::null(), 0);
|
||||||
let traceback = CStr::from_ptr(ffi::lua_tolstring(from, -1, ptr::null_mut()))
|
let traceback = CStr::from_ptr(ffi::lua_tolstring(state, -1, ptr::null_mut()))
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap_or_else(|_| "<could not capture traceback>")
|
.unwrap_or_else(|_| "<could not capture traceback>")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
push_wrapped_error(from, Error::CallbackError(traceback, Arc::new(error)));
|
push_wrapped_error(state, Error::CallbackError(traceback, Arc::new(error)));
|
||||||
|
ffi::lua_remove(state, -2);
|
||||||
} else if !is_wrapped_panic(state, 1) {
|
} else if !is_wrapped_panic(state, 1) {
|
||||||
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
let s = ffi::lua_tolstring(state, 1, ptr::null_mut());
|
||||||
if !s.is_null() {
|
if !s.is_null() {
|
||||||
ffi::luaL_traceback(from, state, s, 0);
|
ffi::luaL_traceback(state, state, s, 0);
|
||||||
} else {
|
} else {
|
||||||
ffi::luaL_traceback(from, state, cstr!("<unprintable lua error>"), 0);
|
ffi::luaL_traceback(state, state, cstr!("<unprintable lua error>"), 0);
|
||||||
}
|
}
|
||||||
|
ffi::lua_remove(state, -2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
|
|
Loading…
Reference in New Issue