Fix a crash when closing the main UI (#904)

* Fix a crash when closing the main Ui

Also make sure to dispose the OpenAL context to not leak memory when
unloading the emulation context.

* Improve keys and 'game already running' dialogs

* Make sure to dispose the page table and ThreadContext

Less memory leaks!

* Fix tests

* Address gdk's comments
This commit is contained in:
Thog 2020-02-06 12:38:24 +01:00 committed by GitHub
parent f2b9a9c2b0
commit a906f2071c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 10 deletions

View File

@ -101,6 +101,7 @@ namespace Ryujinx.Audio
} }
_tracks.Clear(); _tracks.Clear();
_context.Dispose();
} }
/// <summary> /// <summary>

View File

@ -107,6 +107,7 @@ namespace Ryujinx.HLE.HOS
public Keyset KeySet => Device.FileSystem.KeySet; public Keyset KeySet => Device.FileSystem.KeySet;
private bool _hasStarted; private bool _hasStarted;
private bool _isDisposed;
public BlitStruct<ApplicationControlProperty> ControlData { get; set; } public BlitStruct<ApplicationControlProperty> ControlData { get; set; }
@ -740,8 +741,10 @@ namespace Ryujinx.HLE.HOS
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing) if (!_isDisposed && disposing)
{ {
_isDisposed = true;
KProcess terminationProcess = new KProcess(this); KProcess terminationProcess = new KProcess(this);
KThread terminationThread = new KThread(this); KThread terminationThread = new KThread(this);

View File

@ -1131,5 +1131,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
{ {
throw new UndefinedInstructionException(e.Address, e.OpCode); throw new UndefinedInstructionException(e.Address, e.OpCode);
} }
protected override void Destroy()
{
CpuMemory.Dispose();
}
} }
} }

View File

@ -1141,6 +1141,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
{ {
Owner.Translator.Execute(Context, entrypoint); Owner.Translator.Execute(Context, entrypoint);
Context.Dispose();
ThreadExit(); ThreadExit();
} }

View File

@ -51,7 +51,7 @@ namespace Ryujinx
string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys"); string userProfilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".switch", "prod.keys");
if (!File.Exists(appDataPath) && !File.Exists(userProfilePath) && !Migration.IsMigrationNeeded()) if (!File.Exists(appDataPath) && !File.Exists(userProfilePath) && !Migration.IsMigrationNeeded())
{ {
GtkDialog.CreateErrorDialog("Key file was not found. Please refer to `KEYS.md` for more info"); GtkDialog.CreateWarningDialog("Key file was not found", "Please refer to `KEYS.md` for more info");
} }
MainWindow mainWindow = new MainWindow(); MainWindow mainWindow = new MainWindow();

View File

@ -5,19 +5,29 @@ namespace Ryujinx.Ui
{ {
internal class GtkDialog internal class GtkDialog
{ {
internal static void CreateErrorDialog(string errorMessage) internal static void CreateDialog(string title, string text, string secondaryText)
{ {
MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, null) MessageDialog errorDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, null)
{ {
Title = "Ryujinx - Error", Title = title,
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"), Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
Text = "Ryujinx has encountered an error", Text = text,
SecondaryText = errorMessage, SecondaryText = secondaryText,
WindowPosition = WindowPosition.Center WindowPosition = WindowPosition.Center
}; };
errorDialog.SetSizeRequest(100, 20); errorDialog.SetSizeRequest(100, 20);
errorDialog.Run(); errorDialog.Run();
errorDialog.Dispose(); errorDialog.Dispose();
} }
internal static void CreateWarningDialog(string text, string secondaryText)
{
CreateDialog("Ryujinx - Warning", text, secondaryText);
}
internal static void CreateErrorDialog(string errorMessage)
{
CreateDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage);
}
} }
} }

View File

@ -32,6 +32,8 @@ namespace Ryujinx.Ui
private static GlScreen _screen; private static GlScreen _screen;
private static AutoResetEvent _screenExitStatus = new AutoResetEvent(false);
private static ListStore _tableStore; private static ListStore _tableStore;
private static bool _updatingGameTable; private static bool _updatingGameTable;
@ -278,7 +280,7 @@ namespace Ryujinx.Ui
{ {
if (_gameLoaded) if (_gameLoaded)
{ {
GtkDialog.CreateErrorDialog("A game has already been loaded. Please close the emulator and try again"); GtkDialog.CreateDialog("Ryujinx", "A game has already been loaded", "Please close it first and try again.");
} }
else else
{ {
@ -347,6 +349,8 @@ namespace Ryujinx.Ui
_emulationContext = device; _emulationContext = device;
_screenExitStatus.Reset();
#if MACOS_BUILD #if MACOS_BUILD
CreateGameWindow(device); CreateGameWindow(device);
#else #else
@ -393,6 +397,8 @@ namespace Ryujinx.Ui
DiscordIntegrationModule.SwitchToMainMenu(); DiscordIntegrationModule.SwitchToMainMenu();
_screenExitStatus.Set();
Application.Invoke(delegate Application.Invoke(delegate
{ {
_stopEmulation.Sensitive = false; _stopEmulation.Sensitive = false;
@ -432,12 +438,17 @@ namespace Ryujinx.Ui
if (device != null) if (device != null)
{ {
UpdateGameMetadata(device.System.TitleIdText); UpdateGameMetadata(device.System.TitleIdText);
if (_screen != null)
{
_screen.Exit();
_screenExitStatus.WaitOne();
}
} }
Dispose(); Dispose();
Profile.FinishProfiling(); Profile.FinishProfiling();
device?.Dispose();
DiscordIntegrationModule.Exit(); DiscordIntegrationModule.Exit();
Logger.Shutdown(); Logger.Shutdown();
Application.Quit(); Application.Quit();
@ -584,13 +595,11 @@ namespace Ryujinx.Ui
private void Exit_Pressed(object sender, EventArgs args) private void Exit_Pressed(object sender, EventArgs args)
{ {
_screen?.Exit();
End(_emulationContext); End(_emulationContext);
} }
private void Window_Close(object sender, DeleteEventArgs args) private void Window_Close(object sender, DeleteEventArgs args)
{ {
_screen?.Exit();
End(_emulationContext); End(_emulationContext);
} }