`run()` relied on execFile's `timeout`, which only sends the child a
signal: execFile's callback, and so the promise, settles when the child
exits. An nvidia-smi stuck on a hung driver (uninterruptible sleep) never
does, so `readNativeGpu()` stayed pending, every later `?gpu=1` request
joined that promise through `inFlight`, and since the route awaits the
sensors before `getSystemStats()`, CPU and MEM froze too for every device
with GPU Stats on. The backoff (`nvidiaSkipUntil`) only armed once the
child finally exited.
`run()` now races its own unref'd timer and answers undefined at the
deadline, clearing the timer when execFile settles first. The existing
failure path then arms the 60 s backoff as for any failing reader. The
PowerShell RAM probe shares `run()` and gets the same bound.
Test: an nvidia-smi that never calls back answers within the deadline, the
next poll does not run it again, and its late exit changes nothing (the
test fails on the previous `run()`). Checked against a real TERM-ignoring
child on PATH: the read settles at 1.5 s instead of when the child exits.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
host-sensors: never await the PowerShell RAM probe on a read; keep the resolved total and show the memory in use alone until it answers (test with a held PowerShell)
test: rename the Windows sampler test that said the GPU counters are added "for good"
test: make host-sensors.test.ts's @fileoverview describe what that file covers
host-sensors: make the nvidiaSkipUntil JSDoc describe the back-off deadline
docs: Settings Reference says the host readings live inside System Stats and nothing is fetched while it is off
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>