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
This commit is contained in:
Thog 2019-12-26 02:50:17 +01:00 committed by Ac_K
parent 87bfe681ef
commit 55c956e2ec
7 changed files with 293 additions and 31 deletions

View file

@ -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<KProcess>(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