Skip to content

Fix init order of SetupWithClassicDesktopLifetime - #21954

Merged
MrJul merged 4 commits into
AvaloniaUI:mainfrom
MrJul:fix/macos-shutdown-handler
Sep 1, 2026
Merged

Fix init order of SetupWithClassicDesktopLifetime#21954
MrJul merged 4 commits into
AvaloniaUI:mainfrom
MrJul:fix/macos-shutdown-handler

Conversation

@MrJul

@MrJul MrJul commented Aug 10, 2026

Copy link
Copy Markdown
Member

What does the pull request do?

This PR fixes an initialization order bug when AppBuilder.SetupWithClassicDesktopLifetime() is called instead of StartWithClassicDesktopLifetime().

What is the current behavior?

When SetupWithClassicDesktopLifetime is used, internal events are registered before the AppBuilder initializers run: at that point, many subsystems aren't available yet, causing issues such as ShutdownRequested not being hooked up. Additionally, Startup is called way earlier, or might be called twice if Start() is called manually on the created lifetime.

A related problem arises when calling AppBuilder.SetupWithLifetime() manually without Start: the internal event handlers aren't even initialized.

On macOS, this causes the ShutdownRequested event not to be called when quitting the app from the dock, then triggering a double close of the main window (and hitting a debug assertion).

What is the updated/expected behavior with this PR?

StartWithClassicDesktopLifetime, SetupWithClassicDesktopLifetime and SetupWithLifetime initialize the subsystems and event handlers in the same exact order.

Quitting a macOS application raises the ShutdownRequested event correctly and respects its cancellation.

Unit tests have been added.

How was the solution implemented (if it's not obvious)?

An internal ISetupApplicationLifetime is added and implemented by ClassicDesktopStyleApplicationLifetime. The AppBuilder is responsible for calling it to initialize the lifetime in the correct order properly.

Fixed issues

@MrJul MrJul added bug customer-priority Issue reported by a customer with a support agreement. backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Aug 10, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0068218-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul added the backport-candidate-11.3.x Consider this PR for backporting to 11.3 branch label Aug 24, 2026
@jsuarezruiz jsuarezruiz self-assigned this Aug 24, 2026
@MrJul

MrJul commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

I disagree. The whole point of this PR is to make it consistent: Startup is always raised from the same place, here Setup (unfortunately). There might be no Start() call at all!

In other words, Setup(new ClassicDesktopStyleApplicationLifetime()) and SetupWithClassicDesktopLifetime should have the same behavior with regard to when/if Startup is raised. That's why this PR adds it directly to the base builder instead of special-casing just one path.

In v13, we should remove this hack and take the breaking change that Startup is only called when Start is, solving both issues and respecting the arguments.

@MrJul

MrJul commented Sep 1, 2026

Copy link
Copy Markdown
Member Author

Having thought about it more, the fact that Setup was raising Startup is also part of the bug. The whole initialization order was incorrect. I've changed my stance: Startup is now raised only when Start is called, not on Setup.

This makes the whole thing sane, without hacks.

The following numbers helped this decision:

Users of Setup are few, and such users know when their app starts, so the Startup event is irrelevant there, especially since it was called immediately from Setup, which is user-controlled.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0069303-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul
MrJul dismissed jsuarezruiz’s stale review September 1, 2026 14:47

The args are now respected.

@MrJul
MrJul enabled auto-merge September 1, 2026 14:47
@MrJul
MrJul added this pull request to the merge queue Sep 1, 2026
Merged via the queue into AvaloniaUI:main with commit 5d25bd6 Sep 1, 2026
9 checks passed
@MrJul
MrJul deleted the fix/macos-shutdown-handler branch September 1, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-candidate-11.3.x Consider this PR for backporting to 11.3 branch backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch bug customer-priority Issue reported by a customer with a support agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

'Quit' option in dock menu on macOS can't be canceled when SetupWithClassicDesktopLifetime() is used

4 participants