Closed kpreisser closed 1 year ago
I can consistently reproduce the panic using the following C# console program on Windows 10 Version 21H2 x64 (using .NET 7.0.5), even without attaching a debugger (and I assume, but haven't tested, that it would also occur on Linux, as it also occured there on CI):
using Wasmtime;
using var engine = new Engine();
using var module = Module.FromText(engine, "Error", @"
(module
(import """" ""host_start"" (func $host_start))
(import """" ""host_get_trap"" (func $host_get_trap))
(export ""host_get_trap"" (func $host_get_trap))
(start $start)
(func $start
(call $host_start)
)
)
");
using var store = new Store(engine);
using var linker = new Linker(engine);
linker.Define("", "host_start", Function.FromCallback(
store,
(caller, args, results) => { },
Array.Empty<ValueKind>(),
Array.Empty<ValueKind>()));
linker.Define("", "host_get_trap", Function.FromCallback(
store,
(caller, args, results) => throw new Exception("This is an expected exception."),
Array.Empty<ValueKind>(),
Array.Empty<ValueKind>()));
var instance = linker.Instantiate(store, module);
var getTrap = instance.GetFunction("host_get_trap")!;
// This stackalloc seems necessary to trigger the trap at least
// when using wasmtime_func_call_unchecked.
Span<byte> testStack = stackalloc byte[8192];
try
{
getTrap.Invoke();
}
catch (WasmtimeException ex)
{
Console.WriteLine(ex.ToString());
}
Note that this uses Function.Invoke()
which calls wasmtime_func_call
, and uses the UntypedFunctionCallback
that uses wasmtime_func_new
, so it seems unrelated to the unchecked function variants (wasmtime_func_call_unchecked
, wasmtime_func_new_unchecked
).
However, in this case (with wasmtime_func_call
) the panic is returned as trap (TrapException
) with text 0x0 > 0xe04ab7d8f0
and TrapCode.Undefined
(-1), instead of throwing an SEHException
.
When using wasmtime.dll
built from commit https://github.com/bytecodealliance/wasmtime/commit/b453c70d7af6db1550fd7bc17e2e69c88e89323b as Debug, I get the following output when running the above program:
thread '<unnamed>' panicked at '0x0 > 0xdeb7f7d2f0', crates\runtime\src\traphandlers\backtrace.rs:301:13
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library\std\src\panicking.rs:579
1: core::panicking::panic_fmt
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library\core\src\panicking.rs:64
2: wasmtime_runtime::traphandlers::backtrace::Backtrace::trace_through_wasm<ref_mut$<wasmtime_runtime::traphandlers::backtrace::impl$1::new_with_trap_state::closure_env$0> >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers\backtrace.rs:301
3: wasmtime_runtime::traphandlers::backtrace::Backtrace::trace_with_trap_state<wasmtime_runtime::traphandlers::backtrace::impl$1::new_with_trap_state::closure_env$0>
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers\backtrace.rs:150
4: wasmtime_runtime::traphandlers::backtrace::Backtrace::new_with_trap_state
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers\backtrace.rs:100
5: wasmtime_runtime::traphandlers::call_thread_state::CallThreadState::capture_backtrace
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:507
6: wasmtime_runtime::traphandlers::call_thread_state::CallThreadState::unwind_with
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:436
7: wasmtime_runtime::traphandlers::raise_trap::closure$0
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:83
8: wasmtime_runtime::traphandlers::tls::with<never$,wasmtime_runtime::traphandlers::raise_trap::closure_env$0>
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:691
9: wasmtime_runtime::traphandlers::raise_trap
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:83
10: wasmtime_runtime::traphandlers::raise_user_trap
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:98
11: wasmtime::trap::raise
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\trap.rs:74
12: wasmtime::trampoline::func::array_call_shim<wasmtime::func::impl$8::new_unchecked::closure_env$0<wasmtime::store::StoreData,wasmtime::func::impl$0::new::closure_env$0<wasmtime::store::StoreData,wasmtime::store::context::StoreContextMut<wasmtime::store::St
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\trampoline\func.rs:64
13: wasmtime::func::impl$0::call_unchecked_raw::closure$0<wasmtime::store::StoreData>
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:942
14: wasmtime_runtime::traphandlers::catch_traps::call_closure<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:243
15: wasmtime_setjmp
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\helpers.c:55
16: wasmtime_runtime::traphandlers::catch_traps::closure$0<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:225
17: wasmtime_runtime::traphandlers::impl$3::with::closure$0<wasmtime_runtime::traphandlers::catch_traps::closure_env$0<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> > >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:409
18: wasmtime_runtime::traphandlers::tls::set<i32,wasmtime_runtime::traphandlers::impl$3::with::closure_env$0<wasmtime_runtime::traphandlers::catch_traps::closure_env$0<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> > > >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:684
19: wasmtime_runtime::traphandlers::call_thread_state::CallThreadState::with<wasmtime_runtime::traphandlers::catch_traps::closure_env$0<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> > >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:409
20: wasmtime_runtime::traphandlers::catch_traps<wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\runtime\src\traphandlers.rs:224
21: wasmtime::func::invoke_wasm_and_catch_traps<wasmtime::store::StoreData,wasmtime::func::impl$0::call_unchecked_raw::closure_env$0<wasmtime::store::StoreData> >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:1389
22: wasmtime::func::Func::call_unchecked_raw<wasmtime::store::StoreData>
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:940
23: wasmtime::func::Func::call_unchecked<ref_mut$<wasmtime::store::context::StoreContextMut<wasmtime::store::StoreData> > >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:926
24: wasmtime::func::Func::call_impl<wasmtime::store::StoreData>
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:1096
25: wasmtime::func::Func::call<ref_mut$<wasmtime::store::context::StoreContextMut<wasmtime::store::StoreData> > >
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\wasmtime\src\func.rs:879
26: wasmtime::func::wasmtime_func_call::closure$1
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\c-api\src\func.rs:342
27: core::ops::function::FnOnce::call_once<wasmtime::func::wasmtime_func_call::closure_env$1,tuple$<> >
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc\library\core\src\ops\function.rs:250
28: core::panic::unwind_safe::impl$23::call_once<enum2$<core::result::Result<tuple$<>,anyhow::Error> >,wasmtime::func::wasmtime_func_call::closure_env$1>
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc\library\core\src\panic\unwind_safe.rs:271
29: std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<wasmtime::func::wasmtime_func_call::closure_env$1>,enum2$<core::result::Result<tuple$<>,anyhow::Error> > >
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc\library\std\src\panicking.rs:487
30: std::panicking::try::do_catch<core::panic::unwind_safe::AssertUnwindSafe<wasmtime::func::impl$56::into_func::native_call_shim::closure$0::closure_env$0<wasmtime::store::StoreData,wasmtime_wasi::sync::snapshots::preview_0::add_wasi_unstable_to_linker::clos
31: std::panicking::try<enum2$<core::result::Result<tuple$<>,anyhow::Error> >,core::panic::unwind_safe::AssertUnwindSafe<wasmtime::func::wasmtime_func_call::closure_env$1> >
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc\library\std\src\panicking.rs:451
32: std::panic::catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<wasmtime::func::wasmtime_func_call::closure_env$1>,enum2$<core::result::Result<tuple$<>,anyhow::Error> > >
at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc\library\std\src\panic.rs:140
33: wasmtime::func::wasmtime_func_call
at C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime\crates\c-api\src\func.rs:341
34: <unknown>
35: <unknown>
36: <unknown>
37: <unknown>
38: <unknown>
39: coreclr_shutdown_2
40: <unknown>
41: MetaDataGetDispenser
42: MetaDataGetDispenser
43: MetaDataGetDispenser
44: <unknown>
45: coreclr_execute_assembly
46: <unknown>
47: <unknown>
48: corehost_main
49: hostfxr_close
50: hostfxr_close
51: hostfxr_close
52: hostfxr_close
53: hostfxr_main_startupinfo
54: <unknown>
55: <unknown>
56: <unknown>
57: BaseThreadInitThunk
58: RtlUserThreadStart
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Wasmtime.TrapException: 0x0 > 0xdeb7f7d2f0
at Wasmtime.Function.Invoke(ReadOnlySpan`1 arguments) in C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime-dotnet\src\Function.cs:line 309
at Wasmtime.Function.Invoke() in C:\Users\VPC\Desktop\WebAssembly-Test\wasmtime-dotnet\src\Function.cs:line 250
at Program.<Main>$(String[] args) in C:\Users\VPC\Desktop\WebAssembly-Test\TestWasmtime-ReproPanic\Program.cs:line 41
Bisecting shows that this issue appears to have been introduced with commit https://github.com/bytecodealliance/wasmtime/commit/913efdf24d08c44128bd05743e870161e4998663 (bytecodealliance/wasmtime#6262); when using the previous commit https://github.com/bytecodealliance/wasmtime/commit/5b9121f0e252e9156ddbeadc683f1ee571f7e80e, the output is as expected:
Wasmtime.WasmtimeException: This is an expected exception.
---> System.Exception: This is an expected exception.
at Program.<>c.<<Main>$>b__0_1(Caller caller, ReadOnlySpan`1 args, Span`1 results) in C:\Users\VPC\Desktop\WebAssembly-Test\TestWasmtime-ReproPanic\Program.cs:line 28
(...)
I'll see if I can make a pure wasmtime
crate repro.
I've managed to reproduce with this:
#[test]
fn regression() -> Result<()> {
let engine = Engine::default();
let module = Module::new(
&engine,
r#"
(module
(import "" "host_start" (func $host_start))
(import "" "host_get_trap" (func $host_get_trap))
(export "get_trap" (func $host_get_trap))
(start $start)
(func $start
(call $host_start)
)
)
"#,
)?;
let mut store = Store::new(&engine, ());
let mut linker = Linker::new(&engine);
let host_start = Func::new(
&mut store,
FuncType::new([], []),
|_caller, _args, _results| Ok(()),
);
linker.define(&store, "", "host_start", host_start)?;
let host_get_trap = Func::new(
&mut store,
FuncType::new([], []),
|_caller, _args, _results| Err(anyhow::anyhow!("trap!!!")),
);
linker.define(&store, "", "host_get_trap", host_get_trap)?;
let instance = linker.instantiate(&mut store, &module)?;
let get_trap = instance.get_func(&mut store, "get_trap").unwrap();
let err = get_trap.call(&mut store, &[], &mut []).unwrap_err();
assert!(err.to_string().contains("trap!!!"));
Ok(())
}
Thanks for filing an issue and providing a test case!
Thanks for fixing the issue @fitzgen! The unit tests now run successfully (also on my machine).
@kpreisser thanks for fixing this on the .NET SDK side!
Update definition of
wasmtime_func_call_unchecked
. See bytecodealliance/wasmtime#6262Fixes #244
Note: The unit tests run successfully on my machine (Windows 10 x64) e.g. with
dotnet test
or when running them in Visual Studio without debugging; but when I run them in Visual Studio with debugging, the testWasmtime.Tests.ErrorTests.ItPassesCallbackErrorCauseAsInnerException
always fails with aSEHException
, which seems to be caused by a Rust panic (using Wasmtime from commit b453c70d7af6db1550fd7bc17e2e69c88e89323b):I'm not sure what could be causing this, and why it happens only when running the tests with debugging.