Exit with a more severe error code if the program traps. (#1274)

* Exit with a more severe error code if the program traps.

Previously, the wasmtime CLI would return with a regular failure
error code, such as 1 on Unix. However, a program trap indicates a bug
in the program, which can be useful to distinguish from a simple error
status. Check for the trap case, and return an appropriate OS-specific
exit status.

* Use a loop to iterate over the error causes to find Traps.

* Use anyhow's `chain()` iterator.

* For completeness, handle non-Unix and non-Windows platforms too.

* Add a CLI test for a trapping program.

* Replace a manual `.cause` loop with a `.is` call.

* Correct the expected exit status on Windows.

* Use assert_eq/assert_ne so that if these fail, it prints the output.
This commit is contained in:
Dan Gohman
2020-03-11 13:12:26 -07:00
committed by GitHub
parent 81d9a5e6db
commit d44384da8a
3 changed files with 66 additions and 6 deletions

View File

@@ -1,15 +1,22 @@
use anyhow::{bail, Result};
use std::io::Write;
use std::path::Path;
use std::process::Command;
use std::process::{Command, Output};
use tempfile::NamedTempFile;
fn run_wasmtime(args: &[&str]) -> Result<String> {
// Run the wasmtime CLI with the provided args and return the `Output`.
fn run_wasmtime_for_output(args: &[&str]) -> Result<Output> {
let mut me = std::env::current_exe()?;
me.pop(); // chop off the file name
me.pop(); // chop off `deps`
me.push("wasmtime");
let output = Command::new(&me).args(args).output()?;
Command::new(&me).args(args).output().map_err(Into::into)
}
// Run the wasmtime CLI with the provided args and, if it succeeds, return
// the standard output in a `String`.
fn run_wasmtime(args: &[&str]) -> Result<String> {
let output = run_wasmtime_for_output(args)?;
if !output.status.success() {
bail!(
"Failed to execute wasmtime with: {:?}\n{}",
@@ -74,3 +81,27 @@ fn run_wasmtime_simple_wat() -> Result<()> {
])?;
Ok(())
}
// Running a wat that traps.
#[test]
fn run_wasmtime_unreachable_wat() -> Result<()> {
let wasm = build_wasm("tests/wasm/unreachable.wat")?;
let output = run_wasmtime_for_output(&[wasm.path().to_str().unwrap(), "--disable-cache"])?;
assert_ne!(output.stderr, b"");
assert_eq!(output.stdout, b"");
assert!(!output.status.success());
let code = output
.status
.code()
.expect("wasmtime process should exit normally");
// Test for the specific error code Wasmtime uses to indicate a trap return.
#[cfg(unix)]
assert_eq!(code, 128 + libc::SIGABRT);
#[cfg(windows)]
assert_eq!(code, 3);
Ok(())
}