From af8acfce0dbab0864affb5bc8ee4e45bc8c9f4a9 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 9 Jul 2020 21:49:34 +0200 Subject: [PATCH 1/2] Prevent crashes caused by null locked framebuffer. --- src/Windows/Avalonia.Win32/FramebufferManager.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Windows/Avalonia.Win32/FramebufferManager.cs b/src/Windows/Avalonia.Win32/FramebufferManager.cs index 87c5a1bb02..f4c3a80799 100644 --- a/src/Windows/Avalonia.Win32/FramebufferManager.cs +++ b/src/Windows/Avalonia.Win32/FramebufferManager.cs @@ -17,16 +17,18 @@ namespace Avalonia.Win32 public ILockedFramebuffer Lock() { - UnmanagedMethods.RECT rc; - UnmanagedMethods.GetClientRect(_hwnd, out rc); - var width = rc.right - rc.left; - var height = rc.bottom - rc.top; - if ((_fb == null || _fb.Size.Width != width || _fb.Size.Height != height) && width > 0 && height > 0) + UnmanagedMethods.GetClientRect(_hwnd, out var rc); + + var width = Math.Max(1, rc.right - rc.left); + var height = Math.Max(1, rc.bottom - rc.top); + + if ((_fb == null || _fb.Size.Width != width || _fb.Size.Height != height)) { _fb?.Deallocate(); _fb = null; _fb = new WindowFramebuffer(_hwnd, new PixelSize(width, height)); } + return _fb; } } From 1d94f80f7f4392479e1311992db610d89d79100d Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 9 Jul 2020 23:00:46 +0200 Subject: [PATCH 2/2] Dispose window framebuffers. --- src/Shared/PlatformSupport/StandardRuntimePlatform.cs | 10 +++++++--- src/Windows/Avalonia.Win32/FramebufferManager.cs | 8 +++++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs index 03832d3063..d574732e3d 100644 --- a/src/Shared/PlatformSupport/StandardRuntimePlatform.cs +++ b/src/Shared/PlatformSupport/StandardRuntimePlatform.cs @@ -86,11 +86,15 @@ namespace Avalonia.Shared.PlatformSupport #if DEBUG if (Thread.CurrentThread.ManagedThreadId == GCThread?.ManagedThreadId) { - lock(_lock) + lock (_lock) + { if (!IsDisposed) + { Console.Error.WriteLine("Native blob disposal from finalizer thread\nBacktrace: " - + Environment.StackTrace - + "\n\nBlob created by " + _backtrace); + + Environment.StackTrace + + "\n\nBlob created by " + _backtrace); + } + } } #endif DoDispose(); diff --git a/src/Windows/Avalonia.Win32/FramebufferManager.cs b/src/Windows/Avalonia.Win32/FramebufferManager.cs index f4c3a80799..6969a49dad 100644 --- a/src/Windows/Avalonia.Win32/FramebufferManager.cs +++ b/src/Windows/Avalonia.Win32/FramebufferManager.cs @@ -5,7 +5,7 @@ using Avalonia.Win32.Interop; namespace Avalonia.Win32 { - class FramebufferManager : IFramebufferPlatformSurface + class FramebufferManager : IFramebufferPlatformSurface, IDisposable { private readonly IntPtr _hwnd; private WindowFramebuffer _fb; @@ -31,5 +31,11 @@ namespace Avalonia.Win32 return _fb; } + + public void Dispose() + { + _fb?.Deallocate(); + _fb = null; + } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 6e9cb81b11..0ee1342d27 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -389,6 +389,8 @@ namespace Avalonia.Win32 UnregisterClass(_className, GetModuleHandle(null)); _className = null; } + + _framebuffer.Dispose(); } public void Invalidate(Rect rect)