From b1c62559cb64e3d1a6b1df6d11d66cee28f2331f Mon Sep 17 00:00:00 2001 From: kekkon Date: Tue, 20 Jun 2023 18:14:57 +0200 Subject: [PATCH] Make AppHost.Dispose more robust --- src/Ryujinx.Ava/AppHost.cs | 12 ++++-- .../UI/ViewModels/MainWindowViewModel.cs | 3 -- .../Loaders/Processes/ProcessLoader.cs | 10 ++++- .../Loaders/Processes/ProcessResult.cs | 43 +++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs index d3e0ea392..31ae7724a 100644 --- a/src/Ryujinx.Ava/AppHost.cs +++ b/src/Ryujinx.Ava/AppHost.cs @@ -30,6 +30,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.SystemState; +using Ryujinx.HLE.Loaders.Processes; using Ryujinx.Input; using Ryujinx.Input.HLE; using Ryujinx.Ui.Common; @@ -427,9 +428,12 @@ namespace Ryujinx.Ava _isActive = false; - // NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose. - // We only need to wait for all commands submitted during the main gpu loop to be processed. - _gpuDoneEvent.WaitOne(); + if (_renderingStarted) + { + // NOTE: The render loop is allowed to stay alive until the renderer itself is disposed, as it may handle resource dispose. + // We only need to wait for all commands submitted during the main gpu loop to be processed. + _gpuDoneEvent.WaitOne(); + } _gpuDoneEvent.Dispose(); DisplaySleep.Restore(); @@ -445,7 +449,7 @@ namespace Ryujinx.Ava private void Dispose() { - if (Device.Processes != null) + if (!ProcessResult.Failed.Equals(Device?.Processes?.ActiveApplication)) { _viewModel.UpdateGameMetadata(Device.Processes.ActiveApplication.ProgramIdText); } diff --git a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index b85767a5a..2f1809e25 100644 --- a/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -1488,15 +1488,12 @@ namespace Ryujinx.Ava.UI.ViewModels catch (HorizonResultException ex) { // Apphost Cleanup - AppHost = null; SelectedIcon = null; await Dispatcher.UIThread.InvokeAsync(async () => { await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogCorruptedGameError], ex.Message)); }); - - return; } if (!isApplicationLoaded) diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index 0eedc2131..cf9659d27 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -24,7 +24,15 @@ namespace Ryujinx.HLE.Loaders.Processes private ulong _latestPid; - public ProcessResult ActiveApplication => _processesByPid[_latestPid]; + public ProcessResult ActiveApplication + { + get + { + return _processesByPid.TryGetValue(_latestPid, out ProcessResult processResult) + ? processResult + : ProcessResult.Failed; + } + } public ProcessLoader(Switch device) { diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 81e75e270..a3b8b0dca 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -6,12 +6,14 @@ using Ryujinx.Cpu; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.Horizon.Common; +using System; using System.Linq; namespace Ryujinx.HLE.Loaders.Processes { public class ProcessResult { + public static ProcessResult Failed => new(null, new BlitStruct(1), false, false, null, 0, 0, 0, TitleLanguage.AmericanEnglish); private readonly byte _mainThreadPriority; @@ -91,5 +93,46 @@ namespace Ryujinx.HLE.Loaders.Processes return true; } + + protected bool Equals(ProcessResult other) + { + return _mainThreadPriority == other._mainThreadPriority && _mainThreadStackSize == other._mainThreadStackSize && ProcessId == other.ProcessId && Name == other.Name && DisplayVersion == other.DisplayVersion && ProgramId == other.ProgramId && ProgramIdText == other.ProgramIdText && Is64Bit == other.Is64Bit && DiskCacheEnabled == other.DiskCacheEnabled && AllowCodeMemoryForJit == other.AllowCodeMemoryForJit; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((ProcessResult)obj); + } + + public override int GetHashCode() + { + HashCode hashCode = new HashCode(); + hashCode.Add(_mainThreadPriority); + hashCode.Add(_mainThreadStackSize); + hashCode.Add(ProcessId); + hashCode.Add(Name); + hashCode.Add(DisplayVersion); + hashCode.Add(ProgramId); + hashCode.Add(ProgramIdText); + hashCode.Add(Is64Bit); + hashCode.Add(DiskCacheEnabled); + hashCode.Add(AllowCodeMemoryForJit); + return hashCode.ToHashCode(); + } } }