From 232b1012b0c981830ac46bd5024dcc0e35075301 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Thu, 23 Jun 2022 21:53:16 -0300 Subject: [PATCH] Fix ThreadingLock deadlock on invalid access and TerminateProcess (#3407) --- Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 4 +- Ryujinx.Memory/Tracking/MemoryTracking.cs | 51 +++++++++++++--------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index d01c3e3b..4c95821c 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -966,6 +966,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process SignalExitToDebugExited(); SignalExit(); } + + KernelStatic.GetCurrentThread().Exit(); } private void UnpauseAndTerminateAllThreadsExcept(KThread currentThread) @@ -981,7 +983,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process foreach (KThread thread in _threads) { - if ((thread.SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.TerminationPending) + if (thread != currentThread && (thread.SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.TerminationPending) { thread.PrepareForTermination(); } diff --git a/Ryujinx.Memory/Tracking/MemoryTracking.cs b/Ryujinx.Memory/Tracking/MemoryTracking.cs index e9a4793e..c5abb576 100644 --- a/Ryujinx.Memory/Tracking/MemoryTracking.cs +++ b/Ryujinx.Memory/Tracking/MemoryTracking.cs @@ -227,6 +227,8 @@ namespace Ryujinx.Memory.Tracking // Look up the virtual region using the region list. // Signal up the chain to relevant handles. + bool shouldThrow = false; + lock (TrackingLock) { ref var overlaps = ref ThreadStaticArray.Get(); @@ -235,32 +237,41 @@ namespace Ryujinx.Memory.Tracking if (count == 0 && !precise) { - if (!_memoryManager.IsMapped(address)) + if (_memoryManager.IsMapped(address)) { - _invalidAccessHandler?.Invoke(address); - - // We can't continue - it's impossible to remove protection from the page. - // Even if the access handler wants us to continue, we wouldn't be able to. - throw new InvalidMemoryRegionException(); - } - - _memoryManager.TrackingReprotect(address & ~(ulong)(_pageSize - 1), (ulong)_pageSize, MemoryPermission.ReadAndWrite); - return false; // We can't handle this - it's probably a real invalid access. - } - - for (int i = 0; i < count; i++) - { - VirtualRegion region = overlaps[i]; - - if (precise) - { - region.SignalPrecise(address, size, write); + _memoryManager.TrackingReprotect(address & ~(ulong)(_pageSize - 1), (ulong)_pageSize, MemoryPermission.ReadAndWrite); + return false; // We can't handle this - it's probably a real invalid access. } else { - region.Signal(address, size, write); + shouldThrow = true; } } + else + { + for (int i = 0; i < count; i++) + { + VirtualRegion region = overlaps[i]; + + if (precise) + { + region.SignalPrecise(address, size, write); + } + else + { + region.Signal(address, size, write); + } + } + } + } + + if (shouldThrow) + { + _invalidAccessHandler?.Invoke(address); + + // We can't continue - it's impossible to remove protection from the page. + // Even if the access handler wants us to continue, we wouldn't be able to. + throw new InvalidMemoryRegionException(); } return true;