From 55c956e2ec83b2b7f414688c4fe4ed9f1f316935 Mon Sep 17 00:00:00 2001 From: Thog Date: Thu, 26 Dec 2019 02:50:17 +0100 Subject: Make HLE disposable safely (#850) * Make HLE disposable safely This fix the oldest issue with the HLE code: the kernel side disposability. Changelog: - Implement KProcess::UnpauseAndTerminateAllThreadsExcept, KThread::Terminate, KThread::TerminateCurrentProcess, KThread::PrepareForTermiation and the svc post handler accurately. - Implement svcTerminateProcess and svcExitProcess. (both untested) - Fix KHandleTable::Destroy not decrementing refcount of all objects stored in the table. - Spawn a custom KProcess with the maximum priority to terminate every guest KProcess. (terminating kernel emulation safely) - General system stability improvements to enhance the user's experience. * Fix a typo in a comment in KProcess.cs * Address gdk's comments --- .../HOS/Kernel/SupervisorCall/SvcHandler.cs | 10 +++++ Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs | 43 +++++++++++++++++++++- Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs | 3 +- 3 files changed, 54 insertions(+), 2 deletions(-) (limited to 'Ryujinx.HLE/HOS/Kernel/SupervisorCall') diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs index e3a4b375..0bf5e5fa 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs @@ -1,5 +1,6 @@ using ARMeilleure.State; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.HOS.Kernel.Threading; using System; namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall @@ -29,6 +30,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ExecutionContext context = (ExecutionContext)sender; svcFunc(this, context); + + PostSvcHandler(); + } + + private void PostSvcHandler() + { + KThread currentThread = _system.Scheduler.GetCurrentThread(); + + currentThread.HandlePostSyscall(); } } } \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs index 6525628f..7961f124 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs @@ -17,9 +17,41 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall ExitProcess(); } + public KernelResult TerminateProcess64(int handle) + { + return TerminateProcess(handle); + } + + private KernelResult TerminateProcess(int handle) + { + KProcess process = _process.HandleTable.GetObject(handle); + + KernelResult result; + + if (process != null) + { + if (process == _system.Scheduler.GetCurrentProcess()) + { + result = KernelResult.Success; + process.DecrementToZeroWhileTerminatingCurrent(); + } + else + { + result = process.Terminate(); + process.DecrementReferenceCount(); + } + } + else + { + result = KernelResult.InvalidHandle; + } + + return result; + } + private void ExitProcess() { - _system.Scheduler.GetCurrentProcess().Terminate(); + _system.Scheduler.GetCurrentProcess().TerminateCurrentProcess(); } public KernelResult SignalEvent64(int handle) @@ -184,6 +216,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { currentThread.PrintGuestStackTrace(); + // As the process is exiting, this is probably caused by emulation termination. + if (currentThread.Owner.State == ProcessState.Exiting) + { + return; + } + + // TODO: Debug events. + currentThread.Owner.TerminateCurrentProcess(); + throw new GuestBrokeExecutionException(); } else diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs index 9ec0931a..1c2121f0 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs @@ -74,7 +74,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall { 0x72, nameof(SvcHandler.ConnectToPort64) }, { 0x73, nameof(SvcHandler.SetProcessMemoryPermission64) }, { 0x77, nameof(SvcHandler.MapProcessCodeMemory64) }, - { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) } + { 0x78, nameof(SvcHandler.UnmapProcessCodeMemory64) }, + { 0x7B, nameof(SvcHandler.TerminateProcess64) } }; _svcTable64 = new Action[0x80]; -- cgit v1.2.3