ACTUALLY check the status of lua threads before calling resume

This commit is contained in:
kyren 2017-06-17 22:40:09 -04:00
parent 7b00ff02f2
commit edc5fc8ce3
2 changed files with 71 additions and 39 deletions

View File

@ -444,6 +444,9 @@ impl<'lua> LuaThread<'lua> {
lua.push_ref(lua.state, &self.0); lua.push_ref(lua.state, &self.0);
let thread_state = ffi::lua_tothread(lua.state, -1); let thread_state = ffi::lua_tothread(lua.state, -1);
let status = ffi::lua_status(thread_state);
if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
ffi::lua_pop(lua.state, 1); ffi::lua_pop(lua.state, 1);
let args = args.to_lua_multi(lua)?; let args = args.to_lua_multi(lua)?;
@ -465,6 +468,10 @@ impl<'lua> LuaThread<'lua> {
results.push_front(lua.pop_value(thread_state)?); results.push_front(lua.pop_value(thread_state)?);
} }
R::from_lua_multi(results, lua).map(Some) R::from_lua_multi(results, lua).map(Some)
} else {
ffi::lua_pop(lua.state, 1);
Ok(None)
}
}) })
} }
} }

View File

@ -524,13 +524,15 @@ fn test_thread() {
let lua = Lua::new(); let lua = Lua::new();
let thread = lua.create_thread( let thread = lua.create_thread(
lua.eval::<LuaFunction>( lua.eval::<LuaFunction>(
r#"function (s) r#"
function (s)
local sum = s local sum = s
for i = 1,4 do for i = 1,4 do
sum = sum + coroutine.yield(sum) sum = sum + coroutine.yield(sum)
end end
return sum return sum
end"#, end
"#,
).unwrap(), ).unwrap(),
).unwrap(); ).unwrap();
@ -548,11 +550,13 @@ fn test_thread() {
let accumulate = lua.create_thread( let accumulate = lua.create_thread(
lua.eval::<LuaFunction>( lua.eval::<LuaFunction>(
r#"function (sum) r#"
function (sum)
while true do while true do
sum = sum + coroutine.yield(sum) sum = sum + coroutine.yield(sum)
end end
end"#, end
"#,
).unwrap(), ).unwrap(),
).unwrap(); ).unwrap();
@ -565,14 +569,31 @@ fn test_thread() {
assert_eq!(accumulate.status().unwrap(), LuaThreadStatus::Error); assert_eq!(accumulate.status().unwrap(), LuaThreadStatus::Error);
let thread = lua.eval::<LuaThread>( let thread = lua.eval::<LuaThread>(
r#"coroutine.create(function () r#"
coroutine.create(function ()
while true do while true do
coroutine.yield(42) coroutine.yield(42)
end end
end)"#, end)
"#,
).unwrap(); ).unwrap();
assert_eq!(thread.status().unwrap(), LuaThreadStatus::Active); assert_eq!(thread.status().unwrap(), LuaThreadStatus::Active);
assert_eq!(thread.resume::<_, i64>(()).unwrap(), Some(42)); assert_eq!(thread.resume::<_, i64>(()).unwrap(), Some(42));
let thread: LuaThread = lua.eval(
r#"
coroutine.create(function(arg)
assert(arg == 42)
local yieldarg = coroutine.yield(123)
assert(yieldarg == 43)
return 987
end)
"#,
).unwrap();
assert_eq!(thread.resume::<_, u32>(42).unwrap(), Some(123));
assert_eq!(thread.resume::<_, u32>(43).unwrap(), Some(987));
assert_eq!(thread.resume::<_, u32>(()).unwrap(), None);
} }
#[test] #[test]
@ -580,9 +601,11 @@ fn test_lightuserdata() {
let lua = Lua::new(); let lua = Lua::new();
let globals = lua.globals().unwrap(); let globals = lua.globals().unwrap();
lua.load::<()>( lua.load::<()>(
r#"function id(a) r#"
function id(a)
return a return a
end"#, end
"#,
None, None,
).unwrap(); ).unwrap();
let res = globals let res = globals
@ -632,7 +655,9 @@ fn test_result_conversions() {
let globals = lua.globals().unwrap(); let globals = lua.globals().unwrap();
let err = lua.create_function(|lua, _| { let err = lua.create_function(|lua, _| {
lua.pack(Result::Err::<String, String>("only through failure can we succeed".to_string())) lua.pack(Result::Err::<String, String>(
"only through failure can we succeed".to_string(),
))
}).unwrap(); }).unwrap();
let ok = lua.create_function(|lua, _| { let ok = lua.create_function(|lua, _| {
lua.pack(Result::Ok::<String, String>("!".to_string())) lua.pack(Result::Ok::<String, String>("!".to_string()))