dotnet / dotnet/runtime

[mono][interp] NIY assertion crash in WASM Hybrid AOT when GC finalizes native callback delegate

Open
#121,959 3 comments 0 reactions 0 assignees View on GitHub
area-Codegen-AOT-mono
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

## Description

When running a .NET 10 Uno Platform WebAssembly application with Hybrid AOT, the Mono interpreter crashes with a "NIY" (Not Implemented Yet) assertion failure. The crash occurs when the garbage collector finalizes an `SKData` object that has a native callback delegate, and the interpreter attempts to execute a method that wasn't included in the AOT profile.

## Reproduction Steps

1. Create an Uno Platform WebAssembly project targeting `net10.0-browserwasm` with Hybrid AOT enabled
2. Add the following code to `Program.cs`:

```csharp
using System.Runtime.InteropServices;
using SkiaSharp;

static async void TestSkia()
{
var imageBytes = Marshal.AllocHGlobal(100);
SKData.Create(imageBytes, 100, (_, _) =>
{
Console.WriteLine("SKData DISPOSED!");
Marshal.FreeHGlobal(imageBytes);
});

// Force GC to trigger the crash faster
while (true)
{
await Task.Delay(25);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}

static Program()
{
TestSkia();
}
```

3. Build and run the WASM application
4. The crash occurs when GC collects the `SKData` object and invokes the release callback

## Expected behavior

The application should run without crashing. Methods invoked during GC finalization should either be AOT compiled or gracefully fall back to interpretation.

## Actual behavior

The Mono interpreter crashes with an assertion failure:

```
* Assertion at interp.c:4130, condition `' not met, function:interp_exec_method,
MONO interpreter: NIY encountered in method Microsoft.UI.Xaml.Controls.ListViewBase:get_DataFetchSize ()
```

## Stack Trace

```
Assertion at interp.c:4130, condition `' not met
function: interp_exec_method
MONO interpreter: NIY encountered in method Microsoft.UI.Xaml.Controls.ListViewBase:get_DataFetchSize ()
```

The crash appears to occur when:
1. GC runs and finalizes an object with a native callback
2. The callback delegate invokes interpreted code
3. The interpreter encounters a method not in the AOT profile
4. The interpreter hits an unimplemented opcode or calling convention and asserts

## Configuration

- **.NET SDK**: 10.0.100
- **Uno.Sdk**: 6.4.31
- **Target Framework**: `net10.0-browserwasm`
- **SkiaSharp**: Latest compatible version
- **AOT Mode**: Hybrid (partial AOT with interpreter fallback)
- **Browser**: Tested in Chrome/Edge

## Project Configuration

```xml

net10.0-browserwasm
InterpreterAndAOT

```

## Analysis

The issue appears to be in the Mono interpreter's handling of method calls that weren't AOT compiled when those calls originate from:
1. GC finalizer context
2. Native-to-managed callback transitions
3. Delegate invocations during collection

The "NIY" assertion suggests the interpreter encountered an unimplemented code path, possibly related to:
- Calling convention mismatch between AOT and interpreted code
- Missing interpreter implementation for certain opcodes used in the method
- Thread/context issues when transitioning from native GC callbacks back to managed code

## Workaround

Currently, no reliable workaround exists. Possible mitigations:
- Ensure all methods that might be called during finalization are in the AOT profile
- Avoid using native callbacks with finalizable objects in WASM Hybrid AOT scenarios

## Additional Context

This is blocking production use of Uno Platform with SkiaSharp on WebAssembly with Hybrid AOT. The crash is non-deterministic but can be reliably triggered by forcing frequent GC collections.

/cc @pgovind @AaronRobinsonMSFT

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.