Fix stack checks of recursive async function calls (#3088)

* Fix stack checks of recursive async function calls

Previously the stack pointer limit wasn't adjusted, even in the face of
stack switching. This commit updates the logic around the stack limit
calculation to configure it on all async function calls, even if they're
recursive. Synchronous function calls, however, continue to only
configure the stack limit at the start, not for recursive calls.

* Update crates/wasmtime/src/func.rs

Co-authored-by: Peter Huene <peter@huene.dev>

Co-authored-by: Peter Huene <peter@huene.dev>
This commit is contained in:
Alex Crichton
2021-07-14 16:32:30 -05:00
committed by GitHub
parent 73fd702bb7
commit 13d317a0a8
2 changed files with 90 additions and 35 deletions

View File

@@ -610,3 +610,32 @@ fn resume_separate_thread3() {
});
assert!(f.call(&mut store, &[]).is_err());
}
#[test]
fn recursive_async() -> Result<()> {
let mut store = async_store();
let m = Module::new(
store.engine(),
"(module
(func (export \"overflow\") call 0)
(func (export \"normal\"))
)",
)?;
let i = run(Instance::new_async(&mut store, &m, &[]))?;
let overflow = i.get_typed_func::<(), (), _>(&mut store, "overflow")?;
let normal = i.get_typed_func::<(), (), _>(&mut store, "normal")?;
let f2 = Func::wrap0_async(&mut store, move |mut caller| {
Box::new(async move {
// recursive async calls shouldn't immediately stack overflow...
normal.call_async(&mut caller, ()).await?;
// ... but calls that actually stack overflow should indeed stack
// overflow
let err = overflow.call_async(&mut caller, ()).await.unwrap_err();
assert_eq!(err.trap_code(), Some(TrapCode::StackOverflow));
Ok(())
})
});
run(f2.call_async(&mut store, &[]))?;
Ok(())
}