MONO /__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:187 при маршаллинге float в .NET9

В процессе портирования одной библиотеки на WASM обнаружил, что маршаллинг функций, которые принимают float, работает крайне нестабильно и регулярно приводит к вылету в недрах Mono.

float FloatTest   (float test)                    { return test;                 } // Работает
float FloatTest   (char *a, float test)           { return test + a[0];          } // Вылетает
int   FloatTest   (char *a, float test)           { return (int)test + a[0];     } // Работает
int   FloatTest   (float test1, float test2)      { return (int)(test1 + test2); } // Вылетает
void  glClearColor(float, float, float, float);                                    // Вылетает

dotnet.native.z7t3i4ajhl.js:1294 Invalid UTF-8 leading byte 0x000000fe encountered when deserializing a UTF-8 string in wasm memory to a JS string!
warnOnce                                    @   dotnet.native.z7t3i4ajhl.js:1294
UTF8ArrayToString                           @   dotnet.native.z7t3i4ajhl.js:1179
(anonymous)                                 @   strings.ts:76
xe                                          @   strings.ts:68
Fc                                          @   logging.ts:110
$wasm_trace_logger                          @   dotnet.native.hu7iv36mbw.wasm:0x2b63e0
$eglib_log_adapter                          @   dotnet.native.hu7iv36mbw.wasm:0x4af3e
$monoeg_g_logv_nofree                       @   dotnet.native.hu7iv36mbw.wasm:0x4810f
$monoeg_g_log                               @   dotnet.native.hu7iv36mbw.wasm:0x48224
$monoeg_g_log_disabled                      @   dotnet.native.hu7iv36mbw.wasm:0x48272
$mono_wasm_get_interp_to_native_trampoline  @   dotnet.native.hu7iv36mbw.wasm:0x14c780
$ves_pinvoke_method                         @   dotnet.native.hu7iv36mbw.wasm:0x1a34e
$mono_interp_exec_method                    @   dotnet.native.hu7iv36mbw.wasm:0xb4e9
$interp_runtime_invoke                      @   dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke                          @   dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_invoke_checked                @   dotnet.native.hu7iv36mbw.wasm:0xfa4f4
$mono_runtime_try_invoke_byrefs             @   dotnet.native.hu7iv36mbw.wasm:0x100ca6
$ves_icall_InternalInvoke                   @   dotnet.native.hu7iv36mbw.wasm:0xc3b14
$ves_icall_InternalInvoke_raw               @   dotnet.native.hu7iv36mbw.wasm:0xcc6be
$do_icall                                   @   dotnet.native.hu7iv36mbw.wasm:0x1dded
$do_icall_wrapper                           @   dotnet.native.hu7iv36mbw.wasm:0x1a163
$mono_interp_exec_method                    @   dotnet.native.hu7iv36mbw.wasm:0xb3b7
$interp_runtime_invoke                      @   dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke                          @   dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_try_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0xfafda
$mono_runtime_invoke                        @   dotnet.native.hu7iv36mbw.wasm:0xfdbc1
$mono_wasm_invoke_jsexport                  @   dotnet.native.hu7iv36mbw.wasm:0x2b66f8
(anonymous)                                 @   dotnet.native.z7t3i4ajhl.js:811
ccall                                       @   dotnet.native.z7t3i4ajhl.js:6744
(anonymous)                                 @   dotnet.native.z7t3i4ajhl.js:6762
hn                                          @   managed-exports.ts:280
(anonymous)                                 @   managed-exports.ts:65
Pc                                          @   run.ts:71
await in Pc (async)                             
(anonymous)                                 @   main.js:32

logging.ts:129 [MONO] /__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:187 <disabled>
Error
    at Fc (http://localhost:5251/_framework/dotnet.runtime.d1pzlaz2ez.js:3:168832)
    at dotnet.native.wasm.wasm_trace_logger (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[13816]:0x2b63e0)
    at dotnet.native.wasm.eglib_log_adapter (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[949]:0x4af3e)
    at dotnet.native.wasm.monoeg_g_logv_nofree (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[845]:0x4810f)
    at dotnet.native.wasm.monoeg_g_log (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[847]:0x48224)
    at dotnet.native.wasm.monoeg_g_log_disabled (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[848]:0x48272)
    at dotnet.native.wasm.mono_wasm_get_interp_to_native_trampoline (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[5004]:0x14c780)
    at dotnet.native.wasm.ves_pinvoke_method (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[126]:0x1a34e)
    at dotnet.native.wasm.mono_interp_exec_method (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[115]:0xb4e9)
    at dotnet.native.wasm.interp_runtime_invoke (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[158]:0x1b66e)
Fc                                          @   logging.ts:129
$wasm_trace_logger                          @   dotnet.native.hu7iv36mbw.wasm:0x2b63e0
$eglib_log_adapter                          @   dotnet.native.hu7iv36mbw.wasm:0x4af3e
$monoeg_g_logv_nofree                       @   dotnet.native.hu7iv36mbw.wasm:0x4810f
$monoeg_g_log                               @   dotnet.native.hu7iv36mbw.wasm:0x48224
$monoeg_g_log_disabled                      @   dotnet.native.hu7iv36mbw.wasm:0x48272
$mono_wasm_get_interp_to_native_trampoline  @   dotnet.native.hu7iv36mbw.wasm:0x14c780
$ves_pinvoke_method                         @   dotnet.native.hu7iv36mbw.wasm:0x1a34e
$mono_interp_exec_method                    @   dotnet.native.hu7iv36mbw.wasm:0xb4e9
$interp_runtime_invoke                      @   dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke                          @   dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_invoke_checked                @   dotnet.native.hu7iv36mbw.wasm:0xfa4f4
$mono_runtime_try_invoke_byrefs             @   dotnet.native.hu7iv36mbw.wasm:0x100ca6
$ves_icall_InternalInvoke                   @   dotnet.native.hu7iv36mbw.wasm:0xc3b14
$ves_icall_InternalInvoke_raw               @   dotnet.native.hu7iv36mbw.wasm:0xcc6be
$do_icall                                   @   dotnet.native.hu7iv36mbw.wasm:0x1dded
$do_icall_wrapper                           @   dotnet.native.hu7iv36mbw.wasm:0x1a163
$mono_interp_exec_method                    @   dotnet.native.hu7iv36mbw.wasm:0xb3b7
$interp_runtime_invoke                      @   dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke                          @   dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_try_invoke                    @   dotnet.native.hu7iv36mbw.wasm:0xfafda
$mono_runtime_invoke                        @   dotnet.native.hu7iv36mbw.wasm:0xfdbc1
$mono_wasm_invoke_jsexport                  @   dotnet.native.hu7iv36mbw.wasm:0x2b66f8
(anonymous)                                 @   dotnet.native.z7t3i4ajhl.js:811
ccall                                       @   dotnet.native.z7t3i4ajhl.js:6744
(anonymous)                                 @   dotnet.native.z7t3i4ajhl.js:6762
hn                                          @   managed-exports.ts:280
(anonymous)                                 @   managed-exports.ts:65
Pc                                          @   run.ts:71
await in Pc (async)                             
(anonymous)                                 @   main.js:32

Минимальный пример

(на основе стандартного шаблона WebAssembly Browser App для .NET9)

// main.js
import { dotnet } from './_framework/dotnet.js'

const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet
    .withApplicationArguments("start")
    .create();
runMain();

// Program.cs
using System;
using System.Runtime.InteropServices;

internal class Program {
    [DllImport("Marshal")]
    public static extern int test(float test1, float test2, float test3);
    private static void Main(string[] args) {
        Console.WriteLine(test(123, 456, 789));
    }
}

// Marshal.c
int test(float test1, float test2, float test3) {
    return (int)(test1 + test2 + test3);
}

<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
    <PropertyGroup>
        <TargetFramework>net9.0-browser</TargetFramework>
        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
        <WasmBuildNative>true</WasmBuildNative>
    </PropertyGroup>

    <ItemGroup>
        <NativeFileReference Include="Marshal.c" />
    </ItemGroup>
</Project>

Ожидается:

1368 в консоли.

На практике:

Ошибка выше по тексту.

Проблему не решили:

  • Замена [DllImport] на [LibraryImport] (без эффекта).
  • Откат до .NET8 (без эффекта, другим помогало при схожих проблемах).
  • [MarshalAs(UnmanagedType.U4)] на авось, в попытке пропустить маршаллинг для float (без эффекта).

При этом если собрать пример с AOT, то он начинает магическим образом работать.

Более того, после выключения AOT и даже очистки проекта, все скомпилированные ранее с AOT импорты продолжают работать, но только не новые, добавленные после последней AOT компиляции. Но это не касается отладочных сборок, они всё равно не работают (AOT с отладкой несовместим).

Вопрос: Это баг в Mono или я чего-то не понимаю? Если это не баг, то не хочется создавать бессмысленный issue. И второе: какие еще возможны решения, ибо жить вообще без отладки не хочется.


Ответы (0 шт):