Add Wasmtime-specific C API functions to return errors (#1467)

* Add Wasmtime-specific C API functions to return errors

This commit adds new `wasmtime_*` symbols to the C API, many of which
mirror the existing counterparts in the `wasm.h` header. These APIs are
enhanced in a number of respects:

* Detailed error information is now available through a
  `wasmtime_error_t`. Currently this only exposes one function which is
  to extract a string version of the error.

* There is a distinction now between traps and errors during
  instantiation and function calling. Traps only happen if wasm traps,
  and errors can happen for things like runtime type errors when
  interacting with the API.

* APIs have improved safety with respect to embedders where the lengths
  of arrays are now taken as explicit parameters rather than assumed
  from other parameters.

* Handle trap updates

* Update C examples

* Fix memory.c compile on MSVC

* Update test assertions

* Refactor C slightly

* Bare-bones .NET update

* Remove bogus nul handling
This commit is contained in:
Alex Crichton
2020-04-06 15:13:06 -05:00
committed by GitHub
parent 78c548dc8f
commit bd374fd6fc
30 changed files with 817 additions and 403 deletions

View File

@@ -43,9 +43,10 @@ namespace Wasmtime
using var wasi = config.CreateWasi(Store, name);
if (!Interop.wasmtime_linker_define_wasi(Linker, wasi))
var error = Interop.wasmtime_linker_define_wasi(Linker, wasi);
if (error != IntPtr.Zero)
{
throw new WasmtimeException($"Failed to define WASI module '{name}'.");
throw WasmtimeException.FromOwnedError(error);
}
}
@@ -618,12 +619,10 @@ namespace Wasmtime
textVec.size = (UIntPtr)textBytes.Length;
textVec.data = ptr;
if (!Interop.wasmtime_wat2wasm(ref textVec, out var bytes, out var error))
var error = Interop.wasmtime_wat2wasm(ref textVec, out var bytes);
if (error != IntPtr.Zero)
{
var errorSpan = new ReadOnlySpan<byte>(error.data, checked((int)error.size));
var message = Encoding.UTF8.GetString(errorSpan);
Interop.wasm_byte_vec_delete(ref error);
throw new WasmtimeException($"Failed to parse module text: {message}");
throw WasmtimeException.FromOwnedError(error);
}
var byteSpan = new ReadOnlySpan<byte>(bytes.data, checked((int)bytes.size));
@@ -792,7 +791,11 @@ namespace Wasmtime
nameVec.size = (UIntPtr)nameBytes.Length;
nameVec.data = namePtr;
return Interop.wasmtime_linker_define(Linker, ref moduleNameVec, ref nameVec, ext);
var error = Interop.wasmtime_linker_define(Linker, ref moduleNameVec, ref nameVec, ext);
if (error == IntPtr.Zero)
return true;
Interop.wasmtime_error_delete(error);
return false;
}
}
}

View File

@@ -80,8 +80,13 @@ namespace Wasmtime
unsafe
{
Handle = Interop.wasmtime_linker_instantiate(linker, module.Handle, out var trap);
var error = Interop.wasmtime_linker_instantiate(linker, module.Handle, out var handle, out var trap);
Handle = handle;
if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}
if (trap != IntPtr.Zero)
{
throw TrapException.FromOwnedTrap(trap);

View File

@@ -268,6 +268,21 @@ namespace Wasmtime
}
}
internal class ErrorHandle : SafeHandle
{
public ErrorHandle() : base(IntPtr.Zero, true)
{
}
public override bool IsInvalid => handle == IntPtr.Zero;
protected override bool ReleaseHandle()
{
Interop.wasmtime_error_delete(handle);
return true;
}
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct wasm_byte_vec_t
{
@@ -1003,7 +1018,7 @@ namespace Wasmtime
public static extern void wasmtime_config_wasm_multi_value_set(WasmConfigHandle config, [MarshalAs(UnmanagedType.I1)] bool enable);
[DllImport(LibraryName)]
public static extern void wasmtime_config_strategy_set(WasmConfigHandle config, wasmtime_strategy_t strategy);
public static extern IntPtr wasmtime_config_strategy_set(WasmConfigHandle config, wasmtime_strategy_t strategy);
[DllImport(LibraryName)]
public static extern void wasmtime_config_cranelift_debug_verifier_set(WasmConfigHandle config, [MarshalAs(UnmanagedType.I1)] bool enable);
@@ -1013,9 +1028,8 @@ namespace Wasmtime
// Utility functions
[DllImport(LibraryName, CharSet=CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool wasmtime_wat2wasm(ref wasm_byte_vec_t text, out wasm_byte_vec_t bytes, out wasm_byte_vec_t error);
[DllImport(LibraryName)]
public static extern IntPtr wasmtime_wat2wasm(ref wasm_byte_vec_t text, out wasm_byte_vec_t bytes);
// Linking functions
@@ -1029,19 +1043,16 @@ namespace Wasmtime
public static extern void wasmtime_linker_delete(IntPtr linker);
[DllImport(LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool wasmtime_linker_define(LinkerHandle linker, ref wasm_byte_vec_t module, ref wasm_byte_vec_t name, IntPtr externType);
public static extern IntPtr wasmtime_linker_define(LinkerHandle linker, ref wasm_byte_vec_t module, ref wasm_byte_vec_t name, IntPtr externType);
[DllImport(LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool wasmtime_linker_define_wasi(LinkerHandle linker, WasiInstanceHandle wasi);
public static extern IntPtr wasmtime_linker_define_wasi(LinkerHandle linker, WasiInstanceHandle wasi);
[DllImport(LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool wasmtime_linker_define_instance(LinkerHandle linker, ref wasm_byte_vec_t name, InstanceHandle instance);
public static extern IntPtr wasmtime_linker_define_instance(LinkerHandle linker, ref wasm_byte_vec_t name, InstanceHandle instance);
[DllImport(LibraryName)]
public static extern InstanceHandle wasmtime_linker_instantiate(LinkerHandle linker, ModuleHandle module, out IntPtr trap);
public static extern IntPtr wasmtime_linker_instantiate(LinkerHandle linker, ModuleHandle module, out InstanceHandle instance, out IntPtr trap);
// Caller functions
@@ -1050,5 +1061,11 @@ namespace Wasmtime
[DllImport(LibraryName)]
public static extern ExternHandle wasmtime_caller_export_get(IntPtr caller, ref wasm_byte_vec_t name);
[DllImport(LibraryName)]
public static extern void wasmtime_error_message(IntPtr error, out wasm_byte_vec_t message);
[DllImport(LibraryName)]
public static extern void wasmtime_error_delete(IntPtr error);
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Runtime.Serialization;
using System.Text;
namespace Wasmtime
{
@@ -20,5 +21,20 @@ namespace Wasmtime
/// <inheritdoc/>
protected WasmtimeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
internal static WasmtimeException FromOwnedError(IntPtr error)
{
unsafe
{
Interop.wasmtime_error_message(error, out var bytes);
var byteSpan = new ReadOnlySpan<byte>(bytes.data, checked((int)bytes.size));
var message = Encoding.UTF8.GetString(byteSpan);
Interop.wasm_byte_vec_delete(ref bytes);
Interop.wasmtime_error_delete(error);
return new WasmtimeException(message);
}
}
}
}