fix(gateway): reap cgroup PIDs from a fresh read taken after the live-gateway guard

The single cgroup.procs read now feeds only the empty-check and the
live-gateway guard. The guard can take seconds (gateway.status import,
per-PID cmdline with psutil/ps fallback), so killing from that stale list
could SIGKILL a PID that exited and was reused outside the cgroup, and
would miss orphans spawned in the gap. Re-read cgroup.procs for the kill
loop (one small sysfs read), restoring base's kill-set freshness while
keeping the skipped import on the common empty-cgroup stop.
This commit is contained in:
kshitijk4poor authored and kshitij committed 2026-10-02 00:46:21 +05:30
1 parent 0687c5e171
commit 99f1b9afe2
2 files changed
+15 -1

No files matched your search

+6 -1
View File
@@ -97,7 +97,12 @@ def reap_cgroup(cgroup_path: str | None = None) -> int | None:
)
return None
killed = 0
for pid in others:
# Kill from a fresh read: the guard above can take seconds (status import,
# per-PID cmdline/ps fallback), so `others` may hold exited/reused PIDs and
# miss orphans spawned meanwhile.
for pid in _read_cgroup_pids(cgroup_path):
if pid == me:
continue
try:
os.kill(pid, signal.SIGKILL) # windows-footgun: ok — Linux-only (reads /proc, /sys/fs/cgroup; runs from a systemd unit)
killed += 1
+9
View File
@@ -102,3 +102,12 @@ class TestLiveGatewayGuard:
monkeypatch.setattr(cgroup_cleanup.os, "kill", lambda pid, sig: killed.append(pid))
assert cgroup_cleanup.reap_cgroup(cgroup_path) == 1
assert killed == [777]
# The kill set comes from a fresh cgroup.procs read taken after the
# (slow) guard: a PID that exited meanwhile is not signalled (it may be
# reused outside the cgroup) and an orphan spawned meanwhile is reaped.
reads = iter([[777, os.getpid()], [888, os.getpid()]])
monkeypatch.setattr(cgroup_cleanup, "_read_cgroup_pids", lambda _p: next(reads))
killed.clear()
assert cgroup_cleanup.reap_cgroup(cgroup_path) == 1
assert killed == [888]