[mono][interp] NIY assertion crash in WASM Hybrid AOT when GC finalizes native callback delegate
- 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
Assessment
This issue has not been assessed yet.