Fix ThreadingLock deadlock on invalid access and TerminateProcess (#3407)
This commit is contained in:
parent
e747f5cd83
commit
232b1012b0
2 changed files with 34 additions and 21 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in a new issue