Describe the bug
The way CVDisplayLink is used inside PlatformRenderTimer.mm can cause the app to crash on startup, because it expects a display to immediately be available. This is not always the case - our app can update and restart itself automatically, which can happen during Power Nap, when the laptop lid is closed and no external displays are attached.
System.InvalidOperationException: Avalonia.Native was not able to start the RenderTimer. Native error code is: -6661
?, in void AvaloniaNativeRenderTimer.add_Tick(Action<TimeSpan> value)
?, in void ThreadProxyRenderTimer.add_Tick(Action<TimeSpan> value)
?, in void RenderLoop.Add(IRenderLoopTask i)
?, in new ServerCompositor(IRenderLoop renderLoop, IPlatformGraphics platformGraphics, CompositionOptions options, BatchStreamObjectPool<object> batchObjectPool, BatchStreamMemoryPool batchMemoryPool)
?, in new Compositor(IRenderLoop loop, IPlatformGraphics gpu, bool useUiThreadForSynchronousCommits, ICompositorScheduler scheduler, bool reclaimBuffersImmediately, Dispatcher dispatcher, CompositionOptions options) x 3
?, in void AvaloniaNativePlatform.DoInitialize(AvaloniaNativePlatformOptions options)
?, in AvaloniaNativePlatform AvaloniaNativePlatform.Initialize(IntPtr factory, AvaloniaNativePlatformOptions options) x 2
?, in AppBuilder AvaloniaNativePlatformExtensions.UseAvaloniaNative(AppBuilder builder)+() => { }
?, in void AppBuilder.SetupUnsafe()
?, in void AppBuilder.Setup()
?, in AppBuilder AppBuilder.SetupWithLifetime(IApplicationLifetime lifetime)
?, in int ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, string[] args, Action<IClassicDesktopStyleApplicationLifetime> lifetimeBuilder)
?, in void Program.Main(string[] args)
This seems related to, or possibly the same as, #14927.
To Reproduce
Repro steps are a bit annoying given the nature of the edge case. This might be sufficient:
- Build any Avalonia app. The absolute barebones Avalonia .NET App template will work.
- Create the following shell script:
while true; do
./MyAvaloniaApp & pid=$!
sleep 10
kill $pid
done
- Run the script.
- Close the lid and disconnect all cables (displays/power) from the laptop, but keep it in Wi-Fi range.
- Wait some time for Power Nap to happen.
Expected behavior
The app consistently launches 100% of the time. No exceptions are logged in the terminal window.
Avalonia version
11.3.0
OS
macOS
Additional context
We worked around the crash with the following, which we call in Program.Main() just before BuildAvaloniaApp():
[SupportedOSPlatform("macos")]
public static partial class CVDisplayLink
{
private const string CoreVideoLibrary = "/System/Library/Frameworks/CoreVideo.framework/CoreVideo";
[LibraryImport(CoreVideoLibrary)]
private static partial int CVDisplayLinkCreateWithActiveCGDisplays(out IntPtr displayLinkOut);
[LibraryImport(CoreVideoLibrary)]
private static partial void CVDisplayLinkRelease(IntPtr displayLink);
/// <summary>
/// Loop until a display link is available. If no displays are connected, this will wait until one does connect.
/// </summary>
public static async Task AwaitDisplayLink()
{
IntPtr displayLink;
while (CVDisplayLinkCreateWithActiveCGDisplays(out displayLink) != 0) {
await Task.Delay(1000);
}
CVDisplayLinkRelease(displayLink);
}
}
Describe the bug
The way
CVDisplayLinkis used inside PlatformRenderTimer.mm can cause the app to crash on startup, because it expects a display to immediately be available. This is not always the case - our app can update and restart itself automatically, which can happen during Power Nap, when the laptop lid is closed and no external displays are attached.This seems related to, or possibly the same as, #14927.
To Reproduce
Repro steps are a bit annoying given the nature of the edge case. This might be sufficient:
Expected behavior
The app consistently launches 100% of the time. No exceptions are logged in the terminal window.
Avalonia version
11.3.0
OS
macOS
Additional context
We worked around the crash with the following, which we call in
Program.Main()just beforeBuildAvaloniaApp():