Skip to content

Commit

Permalink
[3.0.0] Backport some C-API trap-related changes (#5224)
Browse files Browse the repository at this point in the history
* c-api: Avoid losing error context with instance traps

This commit was a mistake from #5149

* Update how exits are modeled in the C API (#5215)

Previously extracting an exit code was only possibly on a `wasm_trap_t`
which will never successfully have an exit code on it, so the exit code
extractor is moved over to `wasmtime_error_t`. Additionally extracting a
wasm trace from a `wasmtime_error_t` is added since traces happen on
both traps and errors now.
  • Loading branch information
alexcrichton authored Nov 8, 2022
1 parent d4f3851 commit 0102cd7
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 30 deletions.
18 changes: 18 additions & 0 deletions crates/c-api/include/wasmtime/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ WASM_API_EXTERN void wasmtime_error_message(
wasm_name_t *message
);

/**
* \brief Attempts to extract a WASI-specific exit status from this error.
*
* Returns `true` if the error is a WASI "exit" trap and has a return status.
* If `true` is returned then the exit status is returned through the `status`
* pointer. If `false` is returned then this is not a wasi exit trap.
*/
WASM_API_EXTERN bool wasmtime_error_exit_status(const wasmtime_error_t*, int *status);

/**
* \brief Attempts to extract a WebAssembly trace from this error.
*
* This is similar to #wasm_trap_trace except that it takes a #wasmtime_error_t
* as input. The `out` argument will be filled in with the wasm trace, if
* present.
*/
WASM_API_EXTERN void wasmtime_error_wasm_trace(const wasmtime_error_t*, wasm_frame_vec_t *out);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
9 changes: 0 additions & 9 deletions crates/c-api/include/wasmtime/trap.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,6 @@ WASM_API_EXTERN wasm_trap_t *wasmtime_trap_new(const char *msg, size_t msg_len);
*/
WASM_API_EXTERN bool wasmtime_trap_code(const wasm_trap_t*, wasmtime_trap_code_t *code);

/**
* \brief Attempts to extract a WASI-specific exit status from this trap.
*
* Returns `true` if the trap is a WASI "exit" trap and has a return status. If
* `true` is returned then the exit status is returned through the `status`
* pointer. If `false` is returned then this is not a wasi exit trap.
*/
WASM_API_EXTERN bool wasmtime_trap_exit_status(const wasm_trap_t*, int *status);

/**
* \brief Returns a human-readable name for this frame's function.
*
Expand Down
24 changes: 23 additions & 1 deletion crates/c-api/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::wasm_name_t;
use crate::{wasm_frame_vec_t, wasm_name_t};
use anyhow::{anyhow, Error, Result};

#[repr(C)]
Expand Down Expand Up @@ -37,3 +37,25 @@ pub(crate) fn bad_utf8() -> Option<Box<wasmtime_error_t>> {
pub extern "C" fn wasmtime_error_message(error: &wasmtime_error_t, message: &mut wasm_name_t) {
message.set_buffer(format!("{:?}", error.error).into_bytes());
}

#[no_mangle]
pub extern "C" fn wasmtime_error_exit_status(raw: &wasmtime_error_t, status: &mut i32) -> bool {
#[cfg(feature = "wasi")]
if let Some(exit) = raw.error.downcast_ref::<wasmtime_wasi::I32Exit>() {
*status = exit.0;
return true;
}

// Squash unused warnings in wasi-disabled builds.
drop((raw, status));

false
}

#[no_mangle]
pub extern "C" fn wasmtime_error_wasm_trace<'a>(
raw: &'a wasmtime_error_t,
out: &mut wasm_frame_vec_t<'a>,
) {
crate::trap::error_trace(&raw.error, out)
}
11 changes: 6 additions & 5 deletions crates/c-api/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ pub(crate) fn handle_instantiate(
*instance_ptr = i;
None
}
Err(e) => match e.downcast::<Trap>() {
Ok(trap) => {
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(trap.into())));
Err(e) => {
if e.is::<Trap>() {
*trap_ptr = Box::into_raw(Box::new(wasm_trap_t::new(e)));
None
} else {
Some(Box::new(e.into()))
}
Err(e) => Some(Box::new(e.into())),
},
}
}
}

Expand Down
20 changes: 5 additions & 15 deletions crates/c-api/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ pub extern "C" fn wasm_trap_origin(raw: &wasm_trap_t) -> Option<Box<wasm_frame_t

#[no_mangle]
pub extern "C" fn wasm_trap_trace<'a>(raw: &'a wasm_trap_t, out: &mut wasm_frame_vec_t<'a>) {
let trace = match raw.error.downcast_ref::<WasmBacktrace>() {
error_trace(&raw.error, out)
}

pub(crate) fn error_trace<'a>(error: &'a Error, out: &mut wasm_frame_vec_t<'a>) {
let trace = match error.downcast_ref::<WasmBacktrace>() {
Some(trap) => trap,
None => return out.set_buffer(Vec::new()),
};
Expand Down Expand Up @@ -134,20 +138,6 @@ pub extern "C" fn wasmtime_trap_code(raw: &wasm_trap_t, code: &mut i32) -> bool
true
}

#[no_mangle]
pub extern "C" fn wasmtime_trap_exit_status(raw: &wasm_trap_t, status: &mut i32) -> bool {
#[cfg(feature = "wasi")]
if let Some(exit) = raw.error.downcast_ref::<wasmtime_wasi::I32Exit>() {
*status = exit.0;
return true;
}

// Squash unused warnings in wasi-disabled builds.
drop((raw, status));

false
}

#[no_mangle]
pub extern "C" fn wasm_frame_func_index(frame: &wasm_frame_t<'_>) -> u32 {
frame.trace.frames()[frame.idx].func_index()
Expand Down

0 comments on commit 0102cd7

Please sign in to comment.