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 --- Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs | 43 +++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs') 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 -- cgit v1.2.3