dotnet / dotnet/maui

Windows Reentrancy Crash with FontImageSource

Open
#32,808 3 comments 2 reactions 0 assignees View on GitHub
area-fonts area-single-project platform/windows s/triaged s/verified
Dominant language
C#
Stars
23.3k
Forks
2k
Avg merge
1d 15h
Merged PRs (30d)
290

Description

## Summary

A reentrancy crash occurs in .NET MAUI Windows applications when updating a `FontImageSource` during event handlers, specifically when setting the `Source` property of an `Image` control in the `Loaded`
event handler. The crash manifests as a fail-fast exception (0xc000027b) triggered by WinUI's `CXcpDispatcher::CheckReentrancy`.

## Environment

- **MAUI Version**: 9.0.120 (confirmed on 9.0.10 and latest versions)
- **Platform**: Windows (WinUI)
- **Severity**: Random occurrence, requires rapid user interaction to reproduce

## Root Cause

The crash occurs due to the following execution flow:

1. Timer fires and creates a new `CustomImage` instance
2. `CustomImage` constructor subscribes to the `Loaded` event
3. In the `Loaded` event handler, `Source` property is set synchronously to a new `FontImageSource` with a custom font
4. MAUI's `FontImageSourceService.RenderImageSource` is called
5. Win2D/CanvasTextFormat attempts to load the custom font synchronously
6. Font loading triggers a cross-apartment COM call that pumps messages
7. During the message pump, queued pointer input messages are processed
8. WinUI detects reentrancy (processing input while already in an event handler) and triggers fail-fast crash

**Key Stack Frame**: `Microsoft_Maui!Microsoft.Maui.FontImageSourceService.RenderImageSource` (frame 68 in stack trace)

## Reproduction Steps

1. Create a MAUI Windows app with multiple timers that show/hide content containing `Image` controls
2. Set `FontImageSource` with a custom font in the `Loaded` event handler synchronously
3. Rapidly click UI buttons while timers are running
4. Crash occurs randomly when timing aligns font loading with user input

## Repro

[Archive.zip](https://github.com/user-attachments/files/24063427/Archive.zip)

## Current Workaround

Queue the `FontImageSource` assignment on the dispatcher to defer it to a fresh message loop iteration:

```csharp
private void CustomImageLoaded(object sender, EventArgs e)
{
// Using platform-specific dispatcher
var dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
dispatcher.TryEnqueue(() =>
{
Source = new FontImageSource()
{
FontFamily = "AudiowideRegular",
Size = 40,
Glyph = "\u0030",
Color = Colors.Red,
};
});

// OR using cross-platform MAUI Dispatcher
Dispatcher.Dispatch(() =>
{
Source = new FontImageSource() { /* ... */ };
});
}
```

This workaround has been validated and resolves the issue.

## Investigation Needed

- Can FontImageSourceService.RenderImageSource be made fully asynchronous to avoid blocking COM calls during reentrancy-protected zones?
- Should MAUI automatically queue font loading operations to prevent this class of reentrancy issues?
- Is there a way to detect and warn developers when synchronous font operations occur in event handlers?

## WinUI Team Feedback

The WinUI team reviewed this issue and recommends that MAUI either:

- Pause any new dispatch until RenderImageSource completes, OR
- Add the operation to a dispatcher queue automatically

## Additional Notes

- This is difficult for customers to troubleshoot without crash dumps and WinDbg
- The concept of reentrancy in WinUI (vs UWP) is not well-documented
- Single customer reported so far, but workaround is not discoverable without deep debugging knowledge

Contributor guide

Open the contributing guide

Research direction

Start at Microsoft.Maui.FontImageSourceService.RenderImageSource and reproduce the Windows crash with the supplied Archive.zip, focusing on synchronous FontImageSource assignment from the Loaded handler. Compare the dispatcher-queued workaround with the current behavior; done requires a reviewed, reproducible resolution to the reentrancy crash and appropriate validation.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.