Fix ThreadingLock deadlock on invalid access and TerminateProcess (#3407)

This commit is contained in:
gdkchan 2022-06-23 21:53:16 -03:00 committed by GitHub
parent e747f5cd83
commit 232b1012b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 21 deletions

View file

@ -966,6 +966,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
SignalExitToDebugExited(); SignalExitToDebugExited();
SignalExit(); SignalExit();
} }
KernelStatic.GetCurrentThread().Exit();
} }
private void UnpauseAndTerminateAllThreadsExcept(KThread currentThread) private void UnpauseAndTerminateAllThreadsExcept(KThread currentThread)
@ -981,7 +983,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
foreach (KThread thread in _threads) foreach (KThread thread in _threads)
{ {
if ((thread.SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.TerminationPending) if (thread != currentThread && (thread.SchedFlags & ThreadSchedState.LowMask) != ThreadSchedState.TerminationPending)
{ {
thread.PrepareForTermination(); thread.PrepareForTermination();
} }

View file

@ -227,6 +227,8 @@ namespace Ryujinx.Memory.Tracking
// Look up the virtual region using the region list. // Look up the virtual region using the region list.
// Signal up the chain to relevant handles. // Signal up the chain to relevant handles.
bool shouldThrow = false;
lock (TrackingLock) lock (TrackingLock)
{ {
ref var overlaps = ref ThreadStaticArray<VirtualRegion>.Get(); ref var overlaps = ref ThreadStaticArray<VirtualRegion>.Get();
@ -235,32 +237,41 @@ namespace Ryujinx.Memory.Tracking
if (count == 0 && !precise) if (count == 0 && !precise)
{ {
if (!_memoryManager.IsMapped(address)) if (_memoryManager.IsMapped(address))
{ {
_invalidAccessHandler?.Invoke(address); _memoryManager.TrackingReprotect(address & ~(ulong)(_pageSize - 1), (ulong)_pageSize, MemoryPermission.ReadAndWrite);
return false; // We can't handle this - it's probably a real invalid access.
// 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);
} }
else 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; return true;