Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multi-window interaction with the single process work #972

Merged
merged 5 commits into from
Mar 19, 2024

Conversation

halgari
Copy link
Collaborator

@halgari halgari commented Feb 19, 2024

Fixes #968 and #965.

This fixes the above bugs by reworking how we open multiple windows. Namely:

  • Whenever a window opens, create a main process director token to keep the single process director alive
  • Startup Avalonia in a mode that only shuts down when a cancellation token exits
  • Link that cancellation token to the single process director cancellation token
  • Only run the Avalonia startup and the first window on the creation thread, run the rest via the UI dispatcher (this fixes the Regression: Opening a second instance of the App doesn't create a new Window #968 regression)
@halgari halgari requested a review from a team February 19, 2024 16:12
Copy link
Member

@erri120 erri120 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments.

The app now doesn't open anymore, it like the following exists immediately:

_logger.LogInformation("Starting application loop.");
app.Run(MainThreadData.GlobalShutdownToken);
_logger.LogInformation("Application loop ended.");
00:00:01.793 [INFO] Starting UI application
00:00:02.104 [INFO] Starting application loop.
00:00:02.105 [INFO] Application loop ended.
00:00:02.105 [DEBUG] Startup handler returned 0

Edit: MainThreadData.GlobalShutdownToken appears to already be canceled.

@halgari
Copy link
Collaborator Author

halgari commented Feb 19, 2024

Is this in debug mode? Works fine in debug without a debugger attached on my machine (dotnet run). Looks like with a debugger attached it no longer works, I'll look into that

@erri120
Copy link
Member

erri120 commented Feb 19, 2024

Is this in debug mode? Works fine in debug without a debugger attached on my machine (dotnet run). Looks like with a debugger attached it no longer works, I'll look into that

// Otherwise we need to startup Avalonia. This results in lazy loading of avalonia
MainThreadData.MainThreadActions.Enqueue( () =>
{
tcs.SetResult(0);
if (!MainThreadData.IsStartingThread)
{
logger.LogCritical("UI should only start from the main thread");
return -1;
}
provider.GetRequiredService<NxmRpcListener>();
Startup.Main(provider, []);
return 0;
});

tcs.SetResult(0) will "finish" StartUiWindowAsync which finishes await startup.Start(args, _isDebug); in Program.cs.

@halgari halgari requested a review from erri120 February 19, 2024 19:20
@halgari
Copy link
Collaborator Author

halgari commented Feb 19, 2024

This gets us up back and running. I don't like how there's two paths for the code now, where some things only happen under Debug mode, but I need to think how to better manage this in a way where the code is a bit cleaner. Perhaps a lot of this logic can be moved into the SingleProcess project

Copy link
Member

@erri120 erri120 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple windows now work again, however, you're unable to close any windows. If you close a window, an exception is thrown due to AvaloniaUI/Avalonia#14437 and the window stays frozen on screen. The only way to solve this is by manually killing the main process of the app.

This wasn't an issue before. Previously, the exception from AvaloniaUI/Avalonia#14437 would just be thrown, and the window would close without issues.

@halgari
Copy link
Collaborator Author

halgari commented Feb 20, 2024

What process are you going through to get this to happen? I just opened and closed a bunch of windows with this branch and didn't see this exception?

@erri120
Copy link
Member

erri120 commented Feb 20, 2024

What process are you going through to get this to happen? I just opened and closed a bunch of windows with this branch and didn't see this exception?

The exception should always appear in the log, since the underlying issue AvaloniaUI/Avalonia#14437 hasn't been fixed yet.

However, the last two commits of this PR introduced another issue: the window doesn't close properly, and the main process is still running. I had to manually kill the main process before the windows disappeared. This happens when running with a debugger and without.

@halgari
Copy link
Collaborator Author

halgari commented Feb 20, 2024

I can't get this error at all, it all cleanly shuts down for me, I'll switch over to my ubuntu machine and see if I can get it to happen there.

@Al12rs
Copy link
Contributor

Al12rs commented Feb 20, 2024

I'm testing the merge with main and I can reproduce on windows 11.
Make sure you have managed at least one game to create an additional workspace, I think you might need a LoadoutWorkspace to trigger the crash on close.

The issue is that when you have two windows open and close one, that one crashes on close, which in turn crashes the other window as well. For me the second window closes automatically a few seconds after the crash instead of forcing me to close it manually.

@halgari
Copy link
Collaborator Author

halgari commented Feb 20, 2024

Ah I haven't managed a game yet, let me try that

Copy link
Contributor

This PR conflicts with main. You need to rebase the PR before it can be merged.

@Al12rs
Copy link
Contributor

Al12rs commented Mar 14, 2024

@halgari The app crash on close issue was fixed in:

That should unblock work on this PR again.
The changes from main need to be merged in.

Copy link
Contributor

This PR doesn't conflict with main anymore. It can be merged after all status checks have passed and it has been reviewed.

@codecov-commenter
Copy link

Codecov Report

Attention: Patch coverage is 2.17391% with 90 lines in your changes are missing coverage. Please review.

Project coverage is 54.18%. Comparing base (ce086a3) to head (904c274).

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #972      +/-   ##
==========================================
- Coverage   54.89%   54.18%   -0.72%     
==========================================
  Files         669      669              
  Lines       22126    22177      +51     
  Branches     1710     1713       +3     
==========================================
- Hits        12147    12017     -130     
- Misses       9580     9758     +178     
- Partials      399      402       +3     
Flag Coverage Δ
Linux 54.12% <2.17%> (-0.13%) ⬇️
Windows ?
clean_environment_tests 54.18% <2.17%> (-0.71%) ⬇️
macOS 53.52% <2.17%> (-0.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...rc/NexusMods.App.UI/Windows/MainWindowViewModel.cs 69.81% <ø> (-1.36%) ⬇️
src/NexusMods.App/MainThreadData.cs 0.00% <0.00%> (ø)
src/NexusMods.App/StartupHandler.cs 0.00% <0.00%> (ø)
src/NexusMods.App/Program.cs 0.00% <0.00%> (ø)
src/NexusMods.App/Startup.cs 21.31% <5.26%> (-26.69%) ⬇️

... and 28 files with indirect coverage changes

Copy link
Member

@erri120 erri120 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running the app without an attached debugger via dotnet run, the processes remain running after closing the window.

When running the app with an attached debugger and running two instances, you get two processes, not a single process.

@Al12rs Al12rs added this to the v0.4 milestone Mar 19, 2024
@halgari halgari merged commit f0ab142 into main Mar 19, 2024
7 checks passed
@halgari halgari deleted the fix-multi-window branch March 19, 2024 14:35
@Sewer56
Copy link
Member

Sewer56 commented Mar 20, 2024

When Running on Linux, this PR makes it so you can't run the App in an IDE without the debugger attached.

First process spawns 2nd process, then it dies, as far as I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
5 participants