Skip to content

fix(vm): tolerate processes vanishing mid /proc scan#129

Merged
CMGS merged 2 commits into
masterfrom
fix/proc-scan-vanished-process
Jul 13, 2026
Merged

fix(vm): tolerate processes vanishing mid /proc scan#129
CMGS merged 2 commits into
masterfrom
fix/proc-scan-vanished-process

Conversation

@CMGS

@CMGS CMGS commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Problem

Under a 16-way concurrent clone+release burst, vm rm intermittently failed with:

rm: refuse delete: /proc scan errored: read /proc/70367/cmdline: no such process (resolve the host issue and retry)

ScanProcsByBinary walks /proc reading every numeric entry's cmdline before the binary-name filter, so any short-lived process on the host can race the scan. The scan already skipped ENOENT (process gone before open), but a process reaped between open and read surfaces ESRCH from read(2) (fs/proc/base.c returns -ESRCH once the task is gone), which fell through to the fail-closed path and refused the whole batch delete. The same scan backs WithRunningVM's fallback and GC's ensureOrphanVMMDead, so those paths could spuriously fail the same way.

Fix

Gate the fail-closed latch on IsProcessAlive(pid) instead of errno matching: a vanished process cannot be holding the VM's resources, whatever errno its disappearance surfaced; read errors on live processes (EACCES/EIO) still fail closed. The fmt.Errorf wrap is dropped — os.ReadFile's *PathError already carries read /proc/<pid>/cmdline. Hot-path cost: zero — the aliveness probe runs only on the error branch.

ScanProcsByBinary now delegates to an injectable seam so the classification is pinned by deterministic tests: read error + live pid fails closed, read error + vanished pid is skipped, and skipped entries don't drop valid matches.

Verification

  • Kernel behavior confirmed in a Linux container: after a child is reaped, read(2) on its already-open cmdline returns ESRCH ("no such process", not matched by fs.ErrNotExist), a fresh open returns ENOENT, and kill(pid, 0) returns ESRCH — the aliveness gate covers both raced errnos.
  • go test ./utils/ green on Linux (container) and darwin; new TestScanProcsByBinaryReadErrors passes on Linux.
  • make lint 0 issues on both GOOS=linux and GOOS=darwin.

Also bumps the install doc download link to v0.5.1 (release to be published separately).

Fixes #128

CMGS added 2 commits July 13, 2026 15:20
A process exiting between the /proc readdir and its cmdline read made
ScanProcsByBinary fail the whole scan and vm rm refuse the delete: the
scan skipped ENOENT (gone before open) but not ESRCH (reaped between
open and read). Gate the fail-closed path on IsProcessAlive instead of
errno matching: a gone process cannot hold VM resources, whatever errno
its disappearance surfaced.

Fixes #128
@CMGS CMGS merged commit 34567b6 into master Jul 13, 2026
4 checks passed
@CMGS CMGS deleted the fix/proc-scan-vanished-process branch July 13, 2026 07:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vm rm: /proc scan treats a vanished process as a scan error and refuses the delete

1 participant