Set the thread stack guarantee for fibers on Windows.

This commit fixes the Windows implementation of fibers in Wasmtime to
reserve enough staack space for Rust to handle any stack overflow
exceptions.
This commit is contained in:
Peter Huene
2021-03-19 12:50:38 -07:00
parent 8e34022784
commit f556bd18a7
2 changed files with 22 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ use std::ptr;
use winapi::shared::minwindef::*;
use winapi::shared::winerror::ERROR_NOT_SUPPORTED;
use winapi::um::fibersapi::*;
use winapi::um::processthreadsapi::SetThreadStackGuarantee;
use winapi::um::winbase::*;
#[derive(Debug)]
@@ -49,6 +50,13 @@ unsafe extern "system" fn fiber_start<F, A, B, C>(data: LPVOID)
where
F: FnOnce(A, &super::Suspend<A, B, C>) -> C,
{
// Set the stack guarantee to be consistent with what Rust expects for threads
// This value is taken from:
// https://github.com/rust-lang/rust/blob/0d97f7a96877a96015d70ece41ad08bb7af12377/library/std/src/sys/windows/stack_overflow.rs
if SetThreadStackGuarantee(&mut 0x5000) == 0 {
panic!("failed to set fiber stack guarantee");
}
let state = data.cast::<StartState>();
let func = Box::from_raw((*state).initial_closure.get().cast::<F>());
(*state).initial_closure.set(ptr::null_mut());

View File

@@ -29,13 +29,20 @@ fn segfault() -> ! {
}
}
fn overrun_the_stack() -> usize {
let mut a = [0u8; 1024];
if a.as_mut_ptr() as usize == 1 {
return 1;
} else {
return a.as_mut_ptr() as usize + overrun_the_stack();
fn allocate_stack_space() -> ! {
let _a = [0u8; 1024];
for _ in 0..100000 {
allocate_stack_space();
}
unreachable!()
}
fn overrun_the_stack() -> ! {
println!("{}", CONFIRM);
io::stdout().flush().unwrap();
allocate_stack_space();
}
fn run_future<F: Future>(future: F) -> F::Output {
@@ -104,8 +111,6 @@ fn main() {
let store = Store::new(&engine);
let module = Module::new(&engine, "(module)").unwrap();
let _instance = Instance::new(&store, &module, &[]).unwrap();
println!("{}", CONFIRM);
io::stdout().flush().unwrap();
overrun_the_stack();
},
true,
@@ -118,6 +123,7 @@ fn main() {
let module = Module::new(&engine, r#"(import "" "" (func)) (start 0)"#).unwrap();
let segfault = Func::wrap(&store, || segfault());
Instance::new(&store, &module, &[segfault.into()]).unwrap();
unreachable!();
},
false,
),
@@ -130,8 +136,6 @@ fn main() {
let store = Store::new(&engine);
let f = Func::wrap0_async(&store, (), |_, _| {
Box::new(async {
print!("{}", CONFIRM);
io::stdout().flush().unwrap();
overrun_the_stack();
})
});
@@ -150,8 +154,6 @@ fn main() {
let store = Store::new(&engine);
let f = Func::wrap0_async(&store, (), |_, _| {
Box::new(async {
println!("{}", CONFIRM);
io::stdout().flush().unwrap();
overrun_the_stack();
})
});