Skip to content

Commit 30735d5

Browse files
committed
Fix thread recovery when pushing a bad arg
We should not erase thread stack if a bad argument is pushed before resuming the thread.
1 parent 75c23e5 commit 30735d5

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

src/thread.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ impl Thread {
156156
let thread_state = self.state();
157157
unsafe {
158158
let _sg = StackGuard::new(state);
159-
let _thread_sg = StackGuard::with_top(thread_state, 0);
160159

161160
let nargs = args.push_into_stack_multi(&lua)?;
162161
if nargs > 0 {
@@ -165,6 +164,7 @@ impl Thread {
165164
pushed_nargs += nargs;
166165
}
167166

167+
let _thread_sg = StackGuard::with_top(thread_state, 0);
168168
let (_, nresults) = self.resume_inner(&lua, pushed_nargs)?;
169169
check_stack(state, nresults + 1)?;
170170
ffi::lua_xmove(thread_state, state, nresults);
@@ -192,12 +192,12 @@ impl Thread {
192192
let thread_state = self.state();
193193
unsafe {
194194
let _sg = StackGuard::new(state);
195-
let _thread_sg = StackGuard::with_top(thread_state, 0);
196195

197196
check_stack(state, 1)?;
198197
error.push_into_stack(&lua)?;
199198
ffi::lua_xmove(state, thread_state, 1);
200199

200+
let _thread_sg = StackGuard::with_top(thread_state, 0);
201201
let (_, nresults) = self.resume_inner(&lua, ffi::LUA_RESUMEERROR)?;
202202
check_stack(state, nresults + 1)?;
203203
ffi::lua_xmove(thread_state, state, nresults);

tests/thread.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::panic::catch_unwind;
22

3-
use mlua::{Error, Function, Lua, Result, Thread, ThreadStatus};
3+
use mlua::{Error, Function, IntoLua, Lua, Result, Thread, ThreadStatus, Value};
44

55
#[test]
66
fn test_thread() -> Result<()> {
@@ -252,3 +252,24 @@ fn test_thread_resume_error() -> Result<()> {
252252

253253
Ok(())
254254
}
255+
256+
#[test]
257+
fn test_thread_resume_bad_arg() -> Result<()> {
258+
let lua = Lua::new();
259+
260+
struct BadArg;
261+
262+
impl IntoLua for BadArg {
263+
fn into_lua(self, _lua: &Lua) -> Result<Value> {
264+
Err(Error::runtime("bad arg"))
265+
}
266+
}
267+
268+
let f = lua.create_thread(lua.create_function(|_, ()| Ok("okay"))?)?;
269+
let res = f.resume::<()>((123, BadArg));
270+
assert!(matches!(res, Err(Error::RuntimeError(msg)) if msg == "bad arg"));
271+
let res = f.resume::<String>(()).unwrap();
272+
assert_eq!(res, "okay");
273+
274+
Ok(())
275+
}

0 commit comments

Comments
 (0)