Browse Source

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.
pull/1293/head
Dan Gohman 5 years ago
committed by GitHub
parent
commit
d44384da8a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      src/commands/run.rs
  2. 37
      tests/cli_tests.rs
  3. 5
      tests/wasm/unreachable.wat

30
src/commands/run.rs

@ -6,10 +6,11 @@ use std::{
ffi::{OsStr, OsString},
fs::File,
path::{Component, Path, PathBuf},
process,
};
use structopt::{clap::AppSettings, StructOpt};
use wasi_common::preopen_dir;
use wasmtime::{Engine, Instance, Module, Store};
use wasmtime::{Engine, Instance, Module, Store, Trap};
use wasmtime_interface_types::ModuleData;
use wasmtime_wasi::{old::snapshot_0::Wasi as WasiSnapshot0, Wasi};
@ -113,8 +114,31 @@ impl RunCommand {
}
// Load the main wasm module.
self.handle_module(&store, &module_registry)
.with_context(|| format!("failed to run main module `{}`", self.module.display()))?;
match self
.handle_module(&store, &module_registry)
.with_context(|| format!("failed to run main module `{}`", self.module.display()))
{
Ok(()) => (),
Err(e) => {
// If the program exited because of a trap, return an error code
// to the outside environment indicating a more severe problem
// than a simple failure.
if e.is::<Trap>() {
// Print the error message in the usual way.
eprintln!("Error: {:?}", e);
if cfg!(unix) {
// On Unix, return the error code of an abort.
process::exit(128 + libc::SIGABRT);
} else if cfg!(windows) {
// On Windows, return 3.
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/abort?view=vs-2019
process::exit(3);
}
}
return Err(e);
}
}
Ok(())
}

37
tests/cli_tests.rs

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

5
tests/wasm/unreachable.wat

@ -0,0 +1,5 @@
(module
(func (export "_start")
unreachable
)
)
Loading…
Cancel
Save