[Cpu] Stop guest threads at their next import once the host shuts down

Host shutdown only kept guest threads from starting another slice; a thread already inside
guest code kept calling HLE while the services behind it were torn down. Superliminal's job
threads then got a null command buffer from the GPU library, wrote through it, and the process
died with SIGSEGV on its way out.

After shutdown is requested an import now returns to the host entry stub instead of running,
ending that thread's slice; the scheduler already refuses to enter guest code again.

(cherry picked from commit 9e0e8ec0aa8b0bfaa030e5e97d51dbc0223f93e1)
This commit is contained in:
kuba 2026-09-30 15:09:01 +02:00
parent 5ac730ca05
commit 70d1d2f443
1 changed files with 22 additions and 0 deletions

View File

@ -340,6 +340,14 @@ public sealed partial class DirectExecutionBackend
Console.Error.WriteLine(
$"[LOADER][TRACE] bootstrap_call#{num}: op=0x{value:X16} sym_ptr=0x{value2:X16} sym='{symbolText}' out_ptr=0x{num3:X16} ret=0x{num7:X16}");
}
// Once the host is shutting down, a guest thread still running reaches no more HLE: the
// services behind the imports are being torn down, and a title that sees them fail (a null
// command buffer from the GPU library, say) crashes the process on its way out.
if (_forcedGuestExit && !ActiveForcedGuestExit && TryEndGuestSliceForShutdown(argPackPtr))
{
cpuContext[CpuRegister.Rax] = 1uL;
return 1uL;
}
if (!isGuestWorker &&
!ActiveForcedGuestExit &&
ShouldForceGuestExitOnImportLoop(in importStubEntry, num7, num, value, value2))
@ -1794,6 +1802,20 @@ public sealed partial class DirectExecutionBackend
}
}
// Returns the import straight to the host entry stub, which ends this guest slice.
private unsafe bool TryEndGuestSliceForShutdown(nint argPackPtr)
{
ulong sentinel = ActiveEntryReturnSentinelRip;
if (sentinel < 65536 || !TryPatchActiveGuestReturnSlot(sentinel))
{
return false;
}
*(ulong*)(argPackPtr + 96) = sentinel;
ActiveForcedGuestExit = true;
return true;
}
private unsafe bool TryForceGuestExitToHostStub(nint argPackPtr, long dispatchIndex, ulong returnRip, string nid)
{
ulong num = ActiveEntryReturnSentinelRip;