From 1df2c5ce7f52f34bb01e392e8bc4b00cc691614a Mon Sep 17 00:00:00 2001
From: Cristian Carlesso <kentaromiura@gmail.com>
Date: Thu, 15 Feb 2018 12:16:16 +0000
Subject: [PATCH] Gracefully close the app on exit (#12)

* Gracefully close the app on exit

* Application tear down

instead of calling Environment.Exit(0); do a better tear down of the application
---
 Program.cs                      |  4 ++++
 Ryujinx/OsHle/Horizon.cs        | 13 +++++++++++++
 Ryujinx/OsHle/Process.cs        |  4 ++--
 Ryujinx/OsHle/Svc/SvcHandler.cs |  2 +-
 Ryujinx/OsHle/Svc/SvcSystem.cs  |  2 ++
 Ryujinx/Switch.cs               |  9 +++++++++
 6 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/Program.cs b/Program.cs
index 3d4481aa5..88a8a117c 100644
--- a/Program.cs
+++ b/Program.cs
@@ -50,6 +50,10 @@ namespace Ryujinx
 
             using (GLScreen Screen = new GLScreen(Ns, Renderer))
             {
+                Ns.Finish += (Sender, Args) => {
+                    Screen.Exit();
+                };
+
                 Screen.Run(60.0);
             }
 
diff --git a/Ryujinx/OsHle/Horizon.cs b/Ryujinx/OsHle/Horizon.cs
index dd5787302..f31088738 100644
--- a/Ryujinx/OsHle/Horizon.cs
+++ b/Ryujinx/OsHle/Horizon.cs
@@ -4,6 +4,7 @@ using Ryujinx.OsHle.Handles;
 using Ryujinx.OsHle.Utilities;
 using System.Collections.Concurrent;
 using System.IO;
+using System;
 
 namespace Ryujinx.OsHle
 {
@@ -136,6 +137,18 @@ namespace Ryujinx.OsHle
             }
         }
 
+        internal bool ExitProcess(int ProcessId) {
+            Process process;
+            var Success = Processes.TryRemove(ProcessId, out process);
+            if (Success) {
+                process.StopAllThreads();
+            }
+
+            if (Processes.Count == 0) {
+                Ns.OnFinish(EventArgs.Empty);
+            }
+            return Success;
+        }
         internal bool TryGetProcess(int ProcessId, out Process Process)
         {
             if (!Processes.TryGetValue(ProcessId, out Process))
diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx/OsHle/Process.cs
index 653d9dfda..05f12c1a4 100644
--- a/Ryujinx/OsHle/Process.cs
+++ b/Ryujinx/OsHle/Process.cs
@@ -116,7 +116,7 @@ namespace Ryujinx.OsHle
         {
             if (MainThread != null)
             {
-                while (MainThread.Thread.IsAlive)
+                if (MainThread.Thread.IsAlive)
                 {
                     MainThread.Thread.StopExecution();
                 }
@@ -124,7 +124,7 @@ namespace Ryujinx.OsHle
 
             foreach (AThread Thread in TlsSlots.Values)
             {
-                while (Thread.IsAlive)
+                if (Thread.IsAlive)
                 {
                     Thread.StopExecution();
                 }
diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx/OsHle/Svc/SvcHandler.cs
index ad228c45d..2191793a0 100644
--- a/Ryujinx/OsHle/Svc/SvcHandler.cs
+++ b/Ryujinx/OsHle/Svc/SvcHandler.cs
@@ -8,7 +8,6 @@ namespace Ryujinx.OsHle.Svc
     partial class SvcHandler
     {
         private delegate void SvcFunc(ARegisters Registers);
-
         private Dictionary<int, SvcFunc> SvcFuncs;
 
         private Switch  Ns;
@@ -25,6 +24,7 @@ namespace Ryujinx.OsHle.Svc
                 { 0x03, SvcSetMemoryAttribute            },
                 { 0x04, SvcMapMemory                     },
                 { 0x06, SvcQueryMemory                   },
+                { 0x07, SvcExitProcess                   },
                 { 0x08, SvcCreateThread                  },
                 { 0x09, SvcStartThread                   },
                 { 0x0b, SvcSleepThread                   },
diff --git a/Ryujinx/OsHle/Svc/SvcSystem.cs b/Ryujinx/OsHle/Svc/SvcSystem.cs
index 098ddb2f6..09f7e74c3 100644
--- a/Ryujinx/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx/OsHle/Svc/SvcSystem.cs
@@ -9,6 +9,8 @@ namespace Ryujinx.OsHle.Svc
 {
     partial class SvcHandler
     {
+        private void SvcExitProcess(ARegisters Registers) => Ns.Os.ExitProcess(Registers.ProcessId);
+
         private void SvcCloseHandle(ARegisters Registers)
         {
             int Handle = (int)Registers.X0;
diff --git a/Ryujinx/Switch.cs b/Ryujinx/Switch.cs
index 9e5ea7d06..e912da86b 100644
--- a/Ryujinx/Switch.cs
+++ b/Ryujinx/Switch.cs
@@ -24,6 +24,15 @@ namespace Ryujinx
             VFs = new VirtualFs();
         }
 
+        public event EventHandler Finish;
+        internal virtual void OnFinish(EventArgs e)
+        {
+            EventHandler Handler = Finish;
+            if (Handler != null)
+            {
+                Handler(this, e);
+            }
+        }
         public void Dispose()
         {
             Dispose(true);