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:
Dan Gohman
2020-05-13 15:59:43 -07:00
committed by GitHub
parent 08983bf39c
commit fb0b9e3ae6
27 changed files with 268 additions and 64 deletions

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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

View 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))
)

View 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))
)

View 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))
)

View 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))
)

View 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))
)

View 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))
)