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,27 +444,34 @@ 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);
ffi::lua_pop(lua.state, 1);
let args = args.to_lua_multi(lua)?; let status = ffi::lua_status(thread_state);
let nargs = args.len() as c_int; if status == ffi::LUA_YIELD || ffi::lua_gettop(thread_state) > 0 {
check_stack(thread_state, nargs)?; ffi::lua_pop(lua.state, 1);
for arg in args { let args = args.to_lua_multi(lua)?;
lua.push_value(thread_state, arg)?; let nargs = args.len() as c_int;
check_stack(thread_state, nargs)?;
for arg in args {
lua.push_value(thread_state, arg)?;
}
handle_error(
lua.state,
resume_with_traceback(thread_state, lua.state, nargs),
)?;
let nresults = ffi::lua_gettop(thread_state);
let mut results = LuaMultiValue::new();
for _ in 0..nresults {
results.push_front(lua.pop_value(thread_state)?);
}
R::from_lua_multi(results, lua).map(Some)
} else {
ffi::lua_pop(lua.state, 1);
Ok(None)
} }
handle_error(
lua.state,
resume_with_traceback(thread_state, lua.state, nargs),
)?;
let nresults = ffi::lua_gettop(thread_state);
let mut results = LuaMultiValue::new();
for _ in 0..nresults {
results.push_front(lua.pop_value(thread_state)?);
}
R::from_lua_multi(results, lua).map(Some)
}) })
} }
} }

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#"
local sum = s function (s)
for i = 1,4 do local sum = s
sum = sum + coroutine.yield(sum) for i = 1,4 do
end sum = sum + coroutine.yield(sum)
return sum end
end"#, return sum
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#"
while true do function (sum)
sum = sum + coroutine.yield(sum) while true do
end sum = sum + coroutine.yield(sum)
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#"
while true do coroutine.create(function ()
coroutine.yield(42) while true do
end coroutine.yield(42)
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#"
return a function id(a)
end"#, return a
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()))