Browse Source

Fix app shutdown cancellation via window (#15438)

* Don't call dispatcher shutdown, when app shutdown was cancelled

* Assert Dispatcher.UIThread.ShutdownStarted in TryShutdown_Cancellable_By_Preventing_Window_Close
Max Katz 1 year ago
parent
commit
8500621a87

+ 9 - 3
src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs

@@ -163,6 +163,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
 
             _exitCode = exitCode;
             _isShuttingDown = true;
+            var shutdownCancelled = false;
 
             try
             {
@@ -180,6 +181,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
                 if (!force && Windows.Count > 0)
                 {
                     e.Cancel = true;
+                    shutdownCancelled = true;
                     return false;
                 }
 
@@ -189,10 +191,14 @@ namespace Avalonia.Controls.ApplicationLifetimes
             }
             finally
             {
-                _cts?.Cancel();
-                _cts = null;
                 _isShuttingDown = false;
-                Dispatcher.UIThread.InvokeShutdown();
+
+                if (!shutdownCancelled)
+                {
+                    _cts?.Cancel();
+                    _cts = null;
+                    Dispatcher.UIThread.InvokeShutdown();
+                }
             }
 
             return true;

+ 8 - 3
tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs

@@ -355,9 +355,13 @@ namespace Avalonia.Controls.UnitTests
             {
                 lifetime.SetupCore(Array.Empty<string>());
 
-                var hasExit = false;
+                lifetime.Exit += (_, _) => Assert.Fail("lifetime.Exit was called.");
+                Dispatcher.UIThread.ShutdownStarted += UiThreadOnShutdownStarted;
 
-                lifetime.Exit += (_, _) => hasExit = true;
+                static void UiThreadOnShutdownStarted(object sender, EventArgs e)
+                {
+                    Assert.Fail("Dispatcher.UIThread.ShutdownStarted was called.");
+                }
 
                 var windowA = new Window();
 
@@ -378,7 +382,8 @@ namespace Avalonia.Controls.UnitTests
                 lifetime.TryShutdown();
 
                 Assert.Equal(1, raised);
-                Assert.False(hasExit);
+
+                Dispatcher.UIThread.ShutdownStarted -= UiThreadOnShutdownStarted;
             }
         }