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:
@@ -5,6 +5,7 @@ use std::ptr;
|
|||||||
use winapi::shared::minwindef::*;
|
use winapi::shared::minwindef::*;
|
||||||
use winapi::shared::winerror::ERROR_NOT_SUPPORTED;
|
use winapi::shared::winerror::ERROR_NOT_SUPPORTED;
|
||||||
use winapi::um::fibersapi::*;
|
use winapi::um::fibersapi::*;
|
||||||
|
use winapi::um::processthreadsapi::SetThreadStackGuarantee;
|
||||||
use winapi::um::winbase::*;
|
use winapi::um::winbase::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -49,6 +50,13 @@ unsafe extern "system" fn fiber_start<F, A, B, C>(data: LPVOID)
|
|||||||
where
|
where
|
||||||
F: FnOnce(A, &super::Suspend<A, B, C>) -> C,
|
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 state = data.cast::<StartState>();
|
||||||
let func = Box::from_raw((*state).initial_closure.get().cast::<F>());
|
let func = Box::from_raw((*state).initial_closure.get().cast::<F>());
|
||||||
(*state).initial_closure.set(ptr::null_mut());
|
(*state).initial_closure.set(ptr::null_mut());
|
||||||
|
|||||||
@@ -29,13 +29,20 @@ fn segfault() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overrun_the_stack() -> usize {
|
fn allocate_stack_space() -> ! {
|
||||||
let mut a = [0u8; 1024];
|
let _a = [0u8; 1024];
|
||||||
if a.as_mut_ptr() as usize == 1 {
|
|
||||||
return 1;
|
for _ in 0..100000 {
|
||||||
} else {
|
allocate_stack_space();
|
||||||
return a.as_mut_ptr() as usize + overrun_the_stack();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn overrun_the_stack() -> ! {
|
||||||
|
println!("{}", CONFIRM);
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
allocate_stack_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_future<F: Future>(future: F) -> F::Output {
|
fn run_future<F: Future>(future: F) -> F::Output {
|
||||||
@@ -104,8 +111,6 @@ fn main() {
|
|||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
let module = Module::new(&engine, "(module)").unwrap();
|
let module = Module::new(&engine, "(module)").unwrap();
|
||||||
let _instance = Instance::new(&store, &module, &[]).unwrap();
|
let _instance = Instance::new(&store, &module, &[]).unwrap();
|
||||||
println!("{}", CONFIRM);
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
overrun_the_stack();
|
overrun_the_stack();
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
@@ -118,6 +123,7 @@ fn main() {
|
|||||||
let module = Module::new(&engine, r#"(import "" "" (func)) (start 0)"#).unwrap();
|
let module = Module::new(&engine, r#"(import "" "" (func)) (start 0)"#).unwrap();
|
||||||
let segfault = Func::wrap(&store, || segfault());
|
let segfault = Func::wrap(&store, || segfault());
|
||||||
Instance::new(&store, &module, &[segfault.into()]).unwrap();
|
Instance::new(&store, &module, &[segfault.into()]).unwrap();
|
||||||
|
unreachable!();
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
@@ -130,8 +136,6 @@ fn main() {
|
|||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
let f = Func::wrap0_async(&store, (), |_, _| {
|
let f = Func::wrap0_async(&store, (), |_, _| {
|
||||||
Box::new(async {
|
Box::new(async {
|
||||||
print!("{}", CONFIRM);
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
overrun_the_stack();
|
overrun_the_stack();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -150,8 +154,6 @@ fn main() {
|
|||||||
let store = Store::new(&engine);
|
let store = Store::new(&engine);
|
||||||
let f = Func::wrap0_async(&store, (), |_, _| {
|
let f = Func::wrap0_async(&store, (), |_, _| {
|
||||||
Box::new(async {
|
Box::new(async {
|
||||||
println!("{}", CONFIRM);
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
overrun_the_stack();
|
overrun_the_stack();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user