Return anyhow::Error from host functions instead of Trap, redesign Trap#5149
Conversation
Subscribe to Label Actioncc @fitzgen, @kubkon, @peterhuene DetailsThis issue or pull request has been labeled: "fuzzing", "wasi", "wasmtime:api", "wasmtime:c-api"Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
5f4d08f to
74784cd
Compare
|
Ok I'm actually working through a good deal more refactorings for I still have some more documentation I'd like to update, however, and additionally rename |
pchickey
left a comment
There was a problem hiding this comment.
I've sent all my suggestions in as diffs, this is awesome!
This commit refactors how errors are modeled when returned from host functions and additionally refactors how custom errors work with `Trap`. At a high level functions in Wasmtime that previously worked with `Result<T, Trap>` now work with `Result<T>` instead where the error is `anyhow::Error`. This includes functions such as: * Host-defined functions in a `Linker<T>` * `TypedFunc::call` * Host-related callbacks like call hooks Errors are now modeled primarily as `anyhow::Error` throughout Wasmtime. This subsequently removes the need for `Trap` to have the ability to represent all host-defined errors as it previously did. Consequently the `From` implementations for any error into a `Trap` have been removed here and the only embedder-defined way to create a `Trap` is to use `Trap::new` with a custom string. After this commit the distinction between a `Trap` and a host error is the wasm backtrace that it contains. Previously all errors in host functions would flow through a `Trap` and get a wasm backtrace attached to them, but now this only happens if a `Trap` itself is created meaning that arbitrary host-defined errors flowing from a host import to the other side won't get backtraces attached. Some internals of Wasmtime itself were updated or preserved to use `Trap::new` to capture a backtrace where it seemed useful, such as when fuel runs out. The main motivation for this commit is that it now enables hosts to thread a concrete error type from a host function all the way through to where a wasm function was invoked. Previously this could not be done since the host error was wrapped in a `Trap` that didn't provide the ability to get at the internals. A consequence of this commit is that when a host error is returned that isn't a `Trap` we'll capture a backtrace and then won't have a `Trap` to attach it to. To avoid losing the contextual information this commit uses the `Error::context` method to attach the backtrace as contextual information to ensure that the backtrace is itself not lost. This is a breaking change for likely all users of Wasmtime, but it's hoped to be a relatively minor change to workaround. Most use cases can likely change `-> Result<T, Trap>` to `-> Result<T>` and otherwise explicit creation of a `Trap` is largely no longer necessary.
* Trap: avoid a trailing newline in the Display impl which in turn ends up with three newlines between the end of the backtrace and the `Caused by` in the anyhow Debug impl * make BacktraceContext pub, and add tests showing downcasting behavior of anyhow::Error to traps or backtraces
This commit removes special-handling in the `wasmtime::Trap` type for the i32 exit code required by WASI. This is now instead modeled as a specific `I32Exit` error type in the `wasmtime-wasi` crate which is returned by the `proc_exit` hostcall. Embedders which previously tested for i32 exits now downcast to the `I32Exit` value.
This commit removes the ability to create a trap with an arbitrary error
message. The purpose of this commit is to continue the prior trend of
leaning into the `anyhow::Error` type instead of trying to recreate it
with `Trap`. A subsequent simplification to `Trap` after this commit is
that `Trap` will simply be an `enum` of trap codes with no extra
information. This commit is doubly-motivated by the desire to always use
the new `BacktraceContext` type instead of sometimes using that and
sometimes using `Trap`.
Most of the changes here were around updating `Trap::new` calls to
`bail!` calls instead. Tests which assert particular error messages
additionally often needed to use the `:?` formatter instead of the `{}`
formatter because the prior formats the whole `anyhow::Error` and the
latter only formats the top-most error, which now contains the
backtrace.
With prior refactorings there's no more need for `Trap` to be opaque or otherwise contain a backtrace. This commit parse down `Trap` to simply an `enum` which was the old `TrapCode`. All various tests and such were updated to handle this. The main consequence of this commit is that all errors have a `BacktraceContext` context attached to them. This unfortunately means that the backtrace is printed first before the error message or trap code, but given all the prior simplifications that seems worth it at this time.
This feels like a better name given how this has turned out, and additionally this commit removes having both `WasmBacktrace` and `BacktraceContext`.
c111eb2 to
a651f23
Compare
|
@pchickey mind double-checking the most recent few commits to confirm they look ok to you? |
anyhow::Error from host functions instead of Trapanyhow::Error from host functions instead of Trap, redesign Trap
This comment was marked as resolved.
This comment was marked as resolved.
pchickey
left a comment
There was a problem hiding this comment.
Latest commits look good. Sending you the commit to get the c-api building again, basically we need to derive Clone on all the backtrace structures because theres no more hiding it behind an arc. (Should we use an arc inside?)
This commit was a mistake from #5149
* 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.
Change the return value of this function to a `wasmtime_error_t*` instead of the prior `wasm_trap_t*`. This is a leftover from bytecodealliance#5149. Closes bytecodealliance#5257
…ytecodealliance#5262) Change the return value of this function to a `wasmtime_error_t*` instead of the prior `wasm_trap_t*`. This is a leftover from bytecodealliance#5149. Closes bytecodealliance#5257
In Wasmtime 3, `Trap` is now only an Enum (just like `TrapCode` was). See bytecodealliance/wasmtime#5149 I've adjusted the Ruby bindings to match that change: - Moved the trap code constants on `Trap`, removing the `TrapCode` module. - Renamed `Trap#trap_code` to `Trap#trap`. - Made `Trap#message` exclude the Wasm backtrace by default, and instead added a `wasm_backtrace_message` method for that. I chose this name so we can still implement `wasm_backtrace` that returns an Enumerable of traces, if we ever have the need. This is probably fine for now. In the spirit of matching Wasmtime closely, I wonder if we should instead have a single error type (`Wasmtime::Error`) and define `trap_code` and `wasm_backtrace` on it. We can take that on later and suggest merging this as it's a smaller diff and still gets us on Wasmtime 3.
Fixes compatibility with redesigned error handling (Result<T, wasmtime::Trap> -> anyhow::Result<T>). Refs: bytecodealliance/wasmtime#5149 Signed-off-by: Konstantin Shabanov <mail@etehtsea.me>
Fixes compatibility with redesigned error handling (Result<T, wasmtime::Trap> -> anyhow::Result<T>). Refs: bytecodealliance/wasmtime#5149 Signed-off-by: Konstantin Shabanov <mail@etehtsea.me>
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance/wasmtime#5149
this update required changes from the removed `Trap::new` to anyhow! macro, Trap::new was removed in bytecodealliance#5149
This series of commits is a large refactoring of how
Trapworks and is used in Wasmtime. Individual commits have more details but at a high-level the changes implemented here are:Result<T>instead of some working withResult<T, Trap>. For exampleTypedFunc::callreutrnsResult<T>now, in addition to the host-provided closure toFunc::wrap.anyhow::Errorare threaded around as-is, so if the host returns a specific error that error pops out the other end.Trap::i32_exitfunction has been removed in favor of a concretewasi_common::I32Exiterror typeTrap::newfunction has been removed in favor ofanyhow::Errorconstructors likebail!Traptype has been removed and replaced withTrapCode. It's now just a simpleenumWasmBacktracetype that's attached with.context(...)toanyhow::Errorerrors.This is a large refactoring of how traps work in Wasmtime where the main goal is to pare down the responsibility of
Trapand instead letanyhowdo all the heavy lifting. Embedders which handle various kinds of traps various ways will need to be adjusted accordingly.