AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.99k stars 2.25k forks source link

[macOS] CVDisplayLink unavailable crash (on app start) #14927

Open ltetak opened 8 months ago

ltetak commented 8 months ago

Describe the bug

We have a pretty significant amount of logs from the production environment with a stack trace suggesting the app failed to initialize CVDisplayLink

   at Avalonia.Native.Interop.Impl.__MicroComIAvnPlatformRenderTimerProxy.RegisterTick(IAvnActionCallback callback)
   at Avalonia.Native.AvaloniaNativeRenderTimer.add_Tick(Action`1 value)
   at Avalonia.Rendering.ThreadProxyRenderTimer.add_Tick(Action`1 value)
   at Avalonia.Rendering.RenderLoop.Add(IRenderLoopTask i)
   at Avalonia.Rendering.Composition.Server.ServerCompositor..ctor(IRenderLoop renderLoop, IPlatformGraphics platformGraphics, BatchStreamObjectPool`1 batchObjectPool, BatchStreamMemoryPool batchMemoryPool)
   at Avalonia.Rendering.Composition.Compositor..ctor(IRenderLoop loop, IPlatformGraphics gpu, Boolean useUiThreadForSynchronousCommits, ICompositorScheduler scheduler, Boolean reclaimBuffersImmediately, Dispatcher dispatcher)
   at Avalonia.Rendering.Composition.Compositor..ctor(IRenderLoop loop, IPlatformGraphics gpu, Boolean useUiThreadForSynchronousCommits)
   at Avalonia.Rendering.Composition.Compositor..ctor(IPlatformGraphics gpu, Boolean useUiThreadForSynchronousCommits)
   at Avalonia.Native.AvaloniaNativePlatform.DoInitialize(AvaloniaNativePlatformOptions options)
   at Avalonia.Native.AvaloniaNativePlatform.Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
   at Avalonia.Native.AvaloniaNativePlatform.Initialize(AvaloniaNativePlatformOptions options)
   at Avalonia.AvaloniaNativePlatformExtensions.<>c__DisplayClass0_0.<UseAvaloniaNative>b__0()
   at Avalonia.AppBuilder.SetupUnsafe()
   at Avalonia.AppBuilder.Setup()
   at Avalonia.AppBuilder.SetupWithLifetime(IApplicationLifetime lifetime)
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, String[] args, ShutdownMode shutdownMode)

I would assume something happened and the CVDisplayLink callback mechanism failed to initialize. cc: @maxkatz6

To Reproduce

I can't repro it but I would guess disconnecting monitor before starting the app would do the trick.

Expected behavior

fallback to standard timer?

Avalonia version

11.0.7

OS

macOS

Additional context

https://github.com/AvaloniaUI/Avalonia/pull/12652

ltetak commented 8 months ago

I checked the logs again and all crashes happened in the first second after the app started. It also does not relate to a single user (the user could start the app before and after and no user had this issue twice).

maxkatz6 commented 8 months ago

@ltetak are you sure it's reproducible on 11.0.7? I don't think it was ever backported.

maxkatz6 commented 8 months ago

@ltetak is there any special setup on these machines? Multiple displays, maybe? Something that might help testing.

maxkatz6 commented 8 months ago

@ltetak pushed this PR so it can rethrow original status code instead. Can you try once builds are ready? https://github.com/AvaloniaUI/Avalonia/pull/14938

ltetak commented 8 months ago

@maxkatz6 sorry for misleading you. We are using CI build 11.1.999-cibuild0043638-beta (one of my PRs https://github.com/AvaloniaUI/Avalonia/pull/14229).

I don't know these users' configurations. I tried to repro it on my side and I couldn't. #14938 seems a good first step. I will give you the feedback when we have it in prod.

maxkatz6 commented 5 months ago

More debug info https://github.com/AvaloniaUI/Avalonia/pull/14938#issuecomment-2119756057 Native error code is: -6661 is for invalid argument, which doesn't help much.

maxkatz6 commented 5 months ago

@ltetak I don't know if CGGetActiveDisplayList is a right approach, but it might worth a try, yea. Ideally should be double checked how Chromium/qtbase handle that.

maxkatz6 commented 5 months ago

This is interesting https://source.chromium.org/chromium/chromium/src/+/main:ui/display/mac/display_link_mac.cc;l=236?q=CVDisplayLinkCreateWithCGDisplay

ltetak commented 5 months ago

@maxkatz6 I haven't checked this yet but we also have other logs that seem somewhat related

System.Runtime.InteropServices.COMException: BeginDrawing failed
   at IAvnMetalRenderingSession Avalonia.Native.Interop.Impl.__MicroComIAvnMetalRenderTargetProxy.BeginDrawing()
   at IMetalPlatformSurfaceRenderingSession Avalonia.Native.MetalRenderTarget.BeginRendering()
   at ISkiaGpuRenderSession Avalonia.Skia.Metal.SkiaMetalGpu+SkiaMetalRenderTarget.BeginRenderingSession()
   at IDrawingContextImpl Avalonia.Skia.SkiaGpuRenderTarget.CreateDrawingContext(bool useScaledDrawing)
   at void Avalonia.Rendering.Composition.Server.ServerCompositionTarget.Render()
   at void Avalonia.Rendering.Composition.Server.ServerCompositor.RenderCore(bool catchExceptions)
   at void Avalonia.Rendering.Composition.Server.ServerCompositor.RenderReentrancySafe(bool catchExceptions)
   at void Avalonia.Rendering.Composition.Server.ServerCompositor.Render(bool catchExceptions)
   at void Avalonia.Media.MediaContext.SyncCommit(Compositor compositor, bool waitFullRender, bool catchExceptions)
   at void Avalonia.Controls.TopLevel.HandleClosed()
   at void Avalonia.Controls.WindowBase.HandleClosed()
   at void Avalonia.Native.WindowBaseImpl+WindowBaseEvents.Avalonia.Native.Interop.IAvnWindowBaseEvents.Closed()
   at void Avalonia.Native.Interop.Impl.__MicroComIAvnWindowBaseEventsVTable.Closed(Void* this)
   at void Avalonia.Native.DispatcherImpl.RunLoop(CancellationToken token)
   at void Avalonia.Threading.DispatcherFrame.Run(IControlledDispatcherImpl impl)
   at void Avalonia.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at void Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
   at int Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(string[] args)
   at int Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder builder, string[] args, ShutdownMode shutdownMode)