Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update definition of wasmtime_func_call_unchecked. #245

Merged
merged 2 commits into from
May 3, 2023

Conversation

kpreisser
Copy link
Contributor

@kpreisser kpreisser commented Apr 28, 2023

Update definition of wasmtime_func_call_unchecked. See bytecodealliance/wasmtime#6262

Fixes #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 test Wasmtime.Tests.ErrorTests.ItPassesCallbackErrorCauseAsInnerException always fails with a SEHException, which seems to be caused by a Rust panic (using Wasmtime from commit b453c70d7af6db1550fd7bc17e2e69c88e89323b):

Building Test Projects
========== Starting test run ==========
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.3+1b45f5407b (64-bit .NET 7.0.5)
[xUnit.net 00:00:02.83]   Starting:    Wasmtime.Tests
[xUnit.net 00:00:03.40]     Wasmtime.Tests.ErrorTests.ItPassesCallbackErrorCauseAsInnerException [FAIL]
[xUnit.net 00:00:03.40]       Expected a <Wasmtime.WasmtimeException> to be thrown, but found <System.Runtime.InteropServices.SEHException>: "
[xUnit.net 00:00:03.40]       "System.Runtime.InteropServices.SEHException with message "External component has thrown an exception."
[xUnit.net 00:00:03.40]            at Wasmtime.Function.Native.wasmtime_func_call_unchecked(IntPtr context, ExternFunc& func, ValueRaw* args_and_results, UIntPtr args_and_results_len, IntPtr& trap)
[xUnit.net 00:00:03.40]            at Wasmtime.Function.Invoke(Span`1 argumentsAndResults, StoreContext storeContext) in C:\Users\developer4\Desktop\WebAssembly-Tests\wasmtime-dotnet\src\Function.cs:line 419
[xUnit.net 00:00:03.40]            at Wasmtime.Function.InvokeWithoutReturn(Span`1 arguments, StoreContext storeContext) in C:\Users\developer4\Desktop\WebAssembly-Tests\wasmtime-dotnet\src\Function.cs:line 232
[xUnit.net 00:00:03.40]            at Wasmtime.Function.<>c__DisplayClass171_0.<WrapAction>b__0() in C:\Users\developer4\Desktop\WebAssembly-Tests\wasmtime-dotnet\src\Function.Wrap.cs:line 56
[xUnit.net 00:00:03.40]            at FluentAssertions.Specialized.ActionAssertions.InvokeSubject()
[xUnit.net 00:00:03.40]            at FluentAssertions.Specialized.DelegateAssertions`2.InvokeSubjectWithInterception()
[xUnit.net 00:00:03.40]       .
[xUnit.net 00:00:03.40]       Stack Trace:
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.XUnit2TestFramework.Throw(String message)
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.TestFrameworkProvider.Throw(String message)
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.DefaultAssertionStrategy.HandleFailure(String message)
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.AssertionScope.FailWith(Func`1 failReasonFunc)
[xUnit.net 00:00:03.40]            at FluentAssertions.Execution.AssertionScope.FailWith(String message, Object[] args)
[xUnit.net 00:00:03.40]            at FluentAssertions.Specialized.DelegateAssertionsBase`2.ThrowInternal[TException](Exception exception, String because, Object[] becauseArgs)
[xUnit.net 00:00:03.40]            at FluentAssertions.Specialized.DelegateAssertions`2.Throw[TException](String because, Object[] becauseArgs)
[xUnit.net 00:00:03.40]         C:\Users\developer4\Desktop\WebAssembly-Tests\wasmtime-dotnet\tests\ErrorTests.cs(59,0): at Wasmtime.Tests.ErrorTests.ItPassesCallbackErrorCauseAsInnerException()
[xUnit.net 00:00:03.40]            at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
[xUnit.net 00:00:03.40]            at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
The active test run was aborted. Reason: Test host process crashed : thread '<unnamed>' panicked at '0x1 > 0xd6ef1fb140', crates\runtime\src\traphandlers\backtrace.rs:301:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at '0x1 > 0xd6ef1fb1f0', crates\runtime\src\traphandlers\backtrace.rs:301:13
stack backtrace:
   0:     0x7ff8a2844392 - set_vmctx_memory
   1:     0x7ff8a28626fb - set_vmctx_memory
   2:     0x7ff8a283f23a - set_vmctx_memory
   3:     0x7ff8a28440db - set_vmctx_memory
   4:     0x7ff8a28469c9 - set_vmctx_memory
   5:     0x7ff8a284664b - set_vmctx_memory
   6:     0x7ff8a28470f8 - set_vmctx_memory
   7:     0x7ff8a2846fee - set_vmctx_memory
   8:     0x7ff8a2844d79 - set_vmctx_memory
   9:     0x7ff8a2846ca0 - set_vmctx_memory
  10:     0x7ff8a290cd45 - _jit_debug_register_code
  11:     0x7ff8a2799aa5 - set_vmctx_memory
  12:     0x7ff8a2798788 - set_vmctx_memory
  13:     0x7ff8a279849b - set_vmctx_memory
  14:     0x7ff8a278c857 - wasm_module_delete
  15:     0x7ff8a278c9d7 - wasm_module_delete
  16:     0x7ff8a278c7ef - wasm_module_delete
  17:     0x7ff8a278c8b0 - wasm_module_delete
  18:     0x7ff8a23b112c - wasm_module_delete
  19:     0x7ff8a2266794 - wasm_foreign_as_ref_const
  20:     0x7ff8a28c3113 - _jit_debug_register_code
  21:     0x7ff8a225e8f2 - wasmtime_error_delete
  22:     0x7ff8a217cc29 - wasm_foreign_delete
  23:     0x7ff8a217cadb - wasm_foreign_delete
  24:     0x7ff8a228d2f8 - wasmtime_func_call_unchecked
  25:     0x7ff84eb0ad54 - <unknown>
  26:     0x7ff84eb0ab82 - <unknown>
  27:     0x7ff84eb0a9a9 - <unknown>
  28:     0x7ff84eb0a82d - <unknown>
  29:     0x7ff84eb0a6f1 - <unknown>
  30:     0x7ff84eb096ac - <unknown>
  31:     0x7ff84eb06e66 - <unknown>
  32:     0x7ff84eb30e44 - <unknown>
  33:     0x7ff8ac5bf523 - coreclr_shutdown_2
  34:     0x7ff8ac4f2fa4 - <unknown>
  35:     0x7ff84d2f42b9 - <unknown>
  36:     0x7ff84d2f34bf - <unknown>
  37:     0x7ff8a7518393 - <unknown>
  38:     0x7ff84eb0271c - <unknown>
  39:     0x7ff84eb022b6 - <unknown>
  40:     0x7ff84eb01c93 - <unknown>
  41:     0x7ff84eb01bc0 - <unknown>
  42:     0x7ff84eb01b36 - <unknown>
  43:     0x7ff84eb018c8 - <unknown>
  44:     0x7ff84eb01716 - <unknown>
  45:     0x7ff84eb0162c - <unknown>
  46:     0x7ff84eb01582 - <unknown>
  47:     0x7ff84eb01466 - <unknown>
  48:     0x7ff84eb01113 - <unknown>
  49:     0x7ff84eb00ef6 - <unknown>
  50:     0x7ff84eb00dac - <unknown>
  51:     0x7ff84eb00c7c - <unknown>
  52:     0x7ff84eb0070b - <unknown>
  53:     0x7ff84eb003c3 - <unknown>
  54:     0x7ff84eb00200 - <unknown>
  55:     0x7ff84eb000d3 - <unknown>
  56:     0x7ff84cb428ce - <unknown>
  57:     0x7ff84d340501 - <unknown>
  58:     0x7ff84d33fff3 - <unknown>
  59:     0x7ff84d33ff20 - <unknown>
  60:     0x7ff84d33fe91 - <unknown>
  61:     0x7ff84d33f915 - <unknown>
  62:     0x7ff84d33f7e6 - <unknown>
  63:     0x7ff84d33f2ac - <unknown>
  64:     0x7ff84d33f21c - <unknown>
  65:     0x7ff84d33f171 - <unknown>
  66:     0x7ff84d33eb1f - <unknown>
  67:     0x7ff84d33e7d2 - <unknown>
  68:     0x7ff84d33e576 - <unknown>
  69:     0x7ff84d33e4f0 - <unknown>
  70:     0x7ff84d33e495 - <unknown>
  71:     0x7ff84d33e3fa - <unknown>
  72:     0x7ff84d33e042 - <unknown>
  73:     0x7ff84d33df03 - <unknown>
  74:     0x7ff84d33de30 - <unknown>
  75:     0x7ff84d33dd61 - <unknown>
  76:     0x7ff84d33d2c5 - <unknown>
  77:     0x7ff84d33c8b3 - <unknown>
  78:     0x7ff84d33c7e0 - <unknown>
  79:     0x7ff84d33c5db - <unknown>
  80:     0x7ff84d33ae88 - <unknown>
  81:     0x7ff84d33a524 - <unknown>
  82:     0x7ff84d33a213 - <unknown>
  83:     0x7ff84d33a140 - <unknown>
  84:     0x7ff84d33a0a1 - <unknown>
  85:     0x7ff84d339852 - <unknown>
  86:     0x7ff84d339717 - <unknown>
  87:     0x7ff84d33937d - <unknown>
  88:     0x7ff84d3390d3 - <unknown>
  89:     0x7ff84d339000 - <unknown>
  90:     0x7ff84d338f5b - <unknown>
  91:     0x7ff84d338890 - <unknown>
  92:     0x7ff84d338663 - <unknown>
  93:     0x7ff84d338590 - <unknown>
  94:     0x7ff84d3384f0 - <unknown>
  95:     0x7ff84d3380a9 - <unknown>
  96:     0x7ff84d336b73 - <unknown>
  97:     0x7ff84d3363f3 - <unknown>
  98:     0x7ff84d336320 - <unknown>
  99:     0x7ff84d33627c - <unknown>
 100:     0x7ff84d330488 - <unknown>
 101:     0x7ff84d330143 - <unknown>
 102:     0x7ff84d330070 - <unknown>
 103:     0x7ff84d32ffd1 - <unknown>
 104:     0x7ff84d32fa96 - <unknown>
 105:     0x7ff84d32f3bb - <unknown>
 106:     0x7ff84d32ed03 - <unknown>
 107:     0x7ff84d32ec30 - <unknown>
 108:     0x7ff84d32eaab - <unknown>
 109:     0x7ff84d32c7e9 - <unknown>
 110:     0x7ff84d32c323 - <unknown>
 111:     0x7ff84d32c110 - <unknown>
 112:     0x7ff84d32c071 - <unknown>
 113:     0x7ff84d32b6b0 - <unknown>
 114:     0x7ff84d32b513 - <unknown>
 115:     0x7ff8a768abbf - <unknown>
 116:     0x7ff8a749cc98 - <unknown>
 117:     0x7ff8a74b4864 - <unknown>
 118:     0x7ff8a74b46bd - <unknown>
 119:     0x7ff8a74bd948 - <unknown>
 120:     0x7ff84d32b453 - <unknown>
 121:     0x7ff84d32b3e7 - <unknown>
 122:     0x7ff8a749cc98 - <unknown>
 123:     0x7ff84d32b358 - <unknown>
 124:     0x7ff84d329d52 - <unknown>
 125:     0x7ff84d326f73 - <unknown>
 126:     0x7ff8a749cc98 - <unknown>
 127:     0x7ff8a74b4864 - <unknown>
 128:     0x7ff8ac5bf523 - coreclr_shutdown_2
 129:     0x7ff8ac46eed0 - <unknown>
 130:     0x7ff8ac5afe43 - coreclr_execute_assembly
 131:     0x7ff8ac54a2e1 - MetaDataGetDispenser
 132:     0x7ff8ac54a1f7 - MetaDataGetDispenser
 133:     0x7ff8ac54a0e9 - MetaDataGetDispenser
 134:     0x7ff9728c7604 - BaseThreadInitThunk
 135:     0x7ff9745e26a1 - RtlUserThreadStart
thread panicked while panicking. aborting.

========== Test run aborted: 0 Tests (0 Passed, 0 Failed, 0 Skipped) run in < 1 ms ==========

I'm not sure what could be causing this, and why it happens only when running the tests with debugging.

@kpreisser
Copy link
Contributor Author

kpreisser commented Apr 28, 2023

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 bytecodealliance/wasmtime@b453c70 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 bytecodealliance/wasmtime@913efdf (bytecodealliance/wasmtime#6262); when using the previous commit bytecodealliance/wasmtime@5b9121f, 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
(...)

@fitzgen
Copy link
Member

fitzgen commented Apr 28, 2023

I'll see if I can make a pure wasmtime crate repro.

@fitzgen
Copy link
Member

fitzgen commented Apr 28, 2023

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!

fitzgen added a commit to fitzgen/wasmtime that referenced this pull request May 1, 2023
… Wasm

Fixes a regression from bytecodealliance#6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-Authored-By: [email protected]
fitzgen added a commit to fitzgen/wasmtime that referenced this pull request May 1, 2023
… Wasm

Fixes a regression from bytecodealliance#6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-Authored-By: Alex Crichton <[email protected]>
fitzgen added a commit to fitzgen/wasmtime that referenced this pull request May 2, 2023
… Wasm

Fixes a regression from bytecodealliance#6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-Authored-By: Alex Crichton <[email protected]>
github-merge-queue bot pushed a commit to bytecodealliance/wasmtime that referenced this pull request May 2, 2023
… Wasm (#6321)

Fixes a regression from #6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-authored-by: Alex Crichton <[email protected]>
fitzgen added a commit to fitzgen/wasmtime that referenced this pull request May 2, 2023
… Wasm

Fixes a regression from bytecodealliance#6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-Authored-By: Alex Crichton <[email protected]>
github-merge-queue bot pushed a commit to bytecodealliance/wasmtime that referenced this pull request May 3, 2023
…ng Wasm (#6321)

* wasmtime: Fix resetting stack-walking registers when entering/exiting Wasm

Fixes a regression from #6262, originally reported in
bytecodealliance/wasmtime-dotnet#245

The issue was that we would enter Wasm and save the stack-walking registers but
never clear them after Wasm returns. Then if a host-to-host call tried to
capture a stack, we would mistakenly attempt to use those stale registers to
start the stack walk. This mistake would be caught by an assertion, triggering a
panic.

This commit fixes the issue by managing the save/restore in the
`CallThreadState` construction/drop, rather than in the old `set_prev`
method.

Co-Authored-By: Alex Crichton <[email protected]>

* Plumb through `VMRuntimeLimits` when capturing stack traces

This way we can differentiate between the same module loaded in different stores
and avoid leaking other stores' frames into our backtraces.

Co-Authored-By: Jamey Sharp <[email protected]>

---------

Co-authored-by: Alex Crichton <[email protected]>
Co-authored-by: Jamey Sharp <[email protected]>
@kpreisser
Copy link
Contributor Author

Thanks for fixing the issue @fitzgen! The unit tests now run successfully (also on my machine).

@peterhuene peterhuene merged commit e9b3f84 into bytecodealliance:main May 3, 2023
@peterhuene
Copy link
Member

@kpreisser thanks for fixing this on the .NET SDK side!

@kpreisser kpreisser deleted the fix-func-call-unchecked branch May 3, 2023 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

wasmtime_func_call_unchecked signature has changed
3 participants