Change proc_exit to unwind the stack rather than exiting the host process. (#1646)
* Remove Cranelift's OutOfBounds trap, which is no longer used. * Change proc_exit to unwind instead of exit the host process. This implements the semantics in https://github.com/WebAssembly/WASI/pull/235. Fixes #783. Fixes #993. * Fix exit-status tests on Windows. * Revert the wiggle changes and re-introduce the wasi-common implementations. * Move `wasi_proc_exit` into the wasmtime-wasi crate. * Revert the spec_testsuite change. * Remove the old proc_exit implementations. * Make `TrapReason` an implementation detail. * Allow exit status 2 on Windows too. * Fix a documentation link. * Really fix a documentation link.
This commit is contained in:
@@ -182,3 +182,77 @@ fn timeout_in_invoke() -> Result<()> {
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with a valid non-zero exit code, snapshot0 edition.
|
||||
#[test]
|
||||
fn exit2_wasi_snapshot0() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit2_wasi_snapshot0.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
assert_eq!(output.status.code().unwrap(), 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with a valid non-zero exit code, snapshot1 edition.
|
||||
#[test]
|
||||
fn exit2_wasi_snapshot1() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit2_wasi_snapshot1.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
assert_eq!(output.status.code().unwrap(), 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with a valid non-zero exit code, snapshot0 edition.
|
||||
#[test]
|
||||
fn exit125_wasi_snapshot0() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit125_wasi_snapshot0.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
if cfg!(windows) {
|
||||
assert_eq!(output.status.code().unwrap(), 1);
|
||||
} else {
|
||||
assert_eq!(output.status.code().unwrap(), 125);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with a valid non-zero exit code, snapshot1 edition.
|
||||
#[test]
|
||||
fn exit125_wasi_snapshot1() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit125_wasi_snapshot1.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
if cfg!(windows) {
|
||||
assert_eq!(output.status.code().unwrap(), 1);
|
||||
} else {
|
||||
assert_eq!(output.status.code().unwrap(), 125);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with an invalid non-zero exit code, snapshot0 edition.
|
||||
#[test]
|
||||
fn exit126_wasi_snapshot0() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit126_wasi_snapshot0.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
if cfg!(windows) {
|
||||
assert_eq!(output.status.code().unwrap(), 3);
|
||||
} else {
|
||||
assert_eq!(output.status.code().unwrap(), 128 + libc::SIGABRT);
|
||||
}
|
||||
assert!(output.stdout.is_empty());
|
||||
assert!(String::from_utf8_lossy(&output.stderr).contains("invalid exit status"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Exit with an invalid non-zero exit code, snapshot1 edition.
|
||||
#[test]
|
||||
fn exit126_wasi_snapshot1() -> Result<()> {
|
||||
let wasm = build_wasm("tests/wasm/exit126_wasi_snapshot1.wat")?;
|
||||
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
|
||||
if cfg!(windows) {
|
||||
assert_eq!(output.status.code().unwrap(), 3);
|
||||
} else {
|
||||
assert_eq!(output.status.code().unwrap(), 128 + libc::SIGABRT);
|
||||
}
|
||||
assert!(output.stdout.is_empty());
|
||||
assert!(String::from_utf8_lossy(&output.stderr).contains("invalid exit status"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ fn trap_smoke() -> Result<()> {
|
||||
let f = Func::wrap(&store, || -> Result<(), Trap> { Err(Trap::new("test")) });
|
||||
let err = f.call(&[]).unwrap_err().downcast::<Trap>()?;
|
||||
assert_eq!(err.message(), "test");
|
||||
assert!(err.i32_exit_status().is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ fn loops_interruptable() -> anyhow::Result<()> {
|
||||
let iloop = instance.get_func("loop").unwrap().get0::<()>()?;
|
||||
store.interrupt_handle()?.interrupt();
|
||||
let trap = iloop().unwrap_err();
|
||||
assert!(trap.message().contains("wasm trap: interrupt"));
|
||||
assert!(trap.to_string().contains("wasm trap: interrupt"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ fn functions_interruptable() -> anyhow::Result<()> {
|
||||
store.interrupt_handle()?.interrupt();
|
||||
let trap = iloop().unwrap_err();
|
||||
assert!(
|
||||
trap.message().contains("wasm trap: interrupt"),
|
||||
trap.to_string().contains("wasm trap: interrupt"),
|
||||
"{}",
|
||||
trap.message()
|
||||
trap.to_string()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -91,9 +91,9 @@ fn loop_interrupt_from_afar() -> anyhow::Result<()> {
|
||||
let trap = iloop().unwrap_err();
|
||||
thread.join().unwrap();
|
||||
assert!(
|
||||
trap.message().contains("wasm trap: interrupt"),
|
||||
trap.to_string().contains("wasm trap: interrupt"),
|
||||
"bad message: {}",
|
||||
trap.message()
|
||||
trap.to_string()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
@@ -127,9 +127,9 @@ fn function_interrupt_from_afar() -> anyhow::Result<()> {
|
||||
let trap = iloop().unwrap_err();
|
||||
thread.join().unwrap();
|
||||
assert!(
|
||||
trap.message().contains("wasm trap: interrupt"),
|
||||
trap.to_string().contains("wasm trap: interrupt"),
|
||||
"bad message: {}",
|
||||
trap.message()
|
||||
trap.to_string()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ fn host_always_has_some_stack() -> anyhow::Result<()> {
|
||||
// has been exhausted.
|
||||
let trap = foo().unwrap_err();
|
||||
assert!(
|
||||
trap.message().contains("call stack exhausted"),
|
||||
trap.to_string().contains("call stack exhausted"),
|
||||
"{}",
|
||||
trap.message()
|
||||
trap.to_string()
|
||||
);
|
||||
|
||||
// Additionally, however, and this is the crucial test, make sure that the
|
||||
|
||||
8
tests/wasm/exit125_wasi_snapshot0.wat
Normal file
8
tests/wasm/exit125_wasi_snapshot0.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_unstable" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 125))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
8
tests/wasm/exit125_wasi_snapshot1.wat
Normal file
8
tests/wasm/exit125_wasi_snapshot1.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_snapshot_preview1" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 125))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
8
tests/wasm/exit126_wasi_snapshot0.wat
Normal file
8
tests/wasm/exit126_wasi_snapshot0.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_unstable" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 126))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
8
tests/wasm/exit126_wasi_snapshot1.wat
Normal file
8
tests/wasm/exit126_wasi_snapshot1.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_snapshot_preview1" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 126))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
8
tests/wasm/exit2_wasi_snapshot0.wat
Normal file
8
tests/wasm/exit2_wasi_snapshot0.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_unstable" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 2))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
8
tests/wasm/exit2_wasi_snapshot1.wat
Normal file
8
tests/wasm/exit2_wasi_snapshot1.wat
Normal file
@@ -0,0 +1,8 @@
|
||||
(module
|
||||
(import "wasi_snapshot_preview1" "proc_exit"
|
||||
(func $__wasi_proc_exit (param i32)))
|
||||
(func $_start
|
||||
(call $__wasi_proc_exit (i32.const 2))
|
||||
)
|
||||
(export "_start" (func $_start))
|
||||
)
|
||||
Reference in New Issue
Block a user