fix(host): HOS_SAMPLE_ALL can crash the game: the sampler's stack walk (RtlVirtualUnwind) is unguarded #383
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot#383
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What happens
With
HOS_PROFILE=5 HOS_SAMPLE_ALL=<file>(and<file>.gopresent), the game can die with an access violation in thesampler's own thread. Seen once in 8 headless 300 s runs of nightly-34 (Windows 11, Ryzen 5 5600, RX 6700 XT), 43 s in,
at the title screen:
longshot.exe+0x18cb50aeissample_all_thread+0xa9e(from the build's longshot.map); the frames above it are theunwinder. The other 7 runs, same build and route, went the full 300 s.
Why
sample_all_threadinhost/mkw_glue.csuspends each guest thread, takes its context and walks up to 16 frames withRtlLookupFunctionEntry+RtlVirtualUnwind, with nothing around it. The unwinder reads the target thread's stack(saved registers, return addresses). If a step goes wrong (a thread stopped where its unwind data does not describe
the frame, a stack being switched, a stale context), it reads an address that is not mapped, here
0x6e0ca01098, and the access violation is raised in the sampler's thread, which takes the process down.Suggested fix
Make the walk unable to fault:
StackBase / StackLimit, via
NtQueryInformationThreadonce per thread) and stop the walk when it leaves them; and/or__try/__exceptwith clang's SEH support, or a vectored handler that recognises a faultin the sampler thread during a walk and ends that sample).
Either way the sample is just cut short; nothing else changes.
Notes
bold/split): no split code was on any sampled stack inthat run, and the same crash can happen in any build.
RtlLookupFunctionEntry+RtlVirtualUnwindwalk is in two more places inhost/mkw_glue.con main0caf0618(around lines 149 and 388, the other samplers); a shared guarded helper would cover all three.