Filter `_find_tractor_strays` by ppid disposition

Only flag `tractor._child` procs as cross-test ghosts of
THIS run if `ppid==1` (init-adopted real leak) or `ppid`
is in the walk's `seen` set (descendant we missed via
race).

Previously, procs whose `ppid` points to some OTHER live non-`pytest`
(in the use of `acli.ptree pytest`) process belong to a different
tractor app (`piker`, another `pytest` shell, a long-running tractor
daemon) and were being falsely flagged as cross-test ghosts.

Deats,
- post-cmdline-match check via `_ppid_from_proc(pid)`,
  short-circuit on `None` (proc died in-flight).
- expand module docstring to spell out the ownership
  filter rule + its rationale.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
trionics.start_or_cancel
Gud Boi 2026-05-14 12:39:33 -04:00
parent 79dda4cb4a
commit a6d4ac3aac
1 changed files with 24 additions and 2 deletions

View File

@ -224,7 +224,19 @@ def _find_tractor_strays(seen: set[int]) -> list[int]:
''' '''
Scan `/proc/*/cmdline` (+ `/comm` as zombie-safe fallback) for Scan `/proc/*/cmdline` (+ `/comm` as zombie-safe fallback) for
`tractor._child` / `tractor[<aid>]` proctitle matches whose `tractor._child` / `tractor[<aid>]` proctitle matches whose
`pid` is NOT in the `seen` set. `pid` is NOT in the `seen` set AND whose `ppid` disposition
indicates the proc belongs to THIS test run's process tree:
- `ppid == 1` init-adopted (parent died) a real leaked
subactor from this (or a prior killed) test run.
- `ppid in seen` subtree-descendant the recursive walk
missed due to a race (proc appeared between iterations).
Procs whose `ppid` points to some OTHER live, non-pytest
process are skipped they belong to a different tractor app
(e.g. `piker`, another `pytest` invocation in another shell,
a long-running tractor daemon) and falsely flagging them as
"cross-test ghosts" of THIS run is misleading.
Used by `dump_proc_tree(include_strays=True)` to surface ghost Used by `dump_proc_tree(include_strays=True)` to surface ghost
subactor trees from PRIOR test runs that aren't descendants of subactor trees from PRIOR test runs that aren't descendants of
@ -256,7 +268,17 @@ def _find_tractor_strays(seen: set[int]) -> list[int]:
pid: int = int(entry.name) pid: int = int(entry.name)
if pid in seen: if pid in seen:
continue continue
if _is_tractor_subactor(pid): if not _is_tractor_subactor(pid):
continue
# ownership filter: only flag procs whose `ppid` ties them
# back to THIS test run (init-adopted orphan, or a
# descendant the walk missed).
ppid: int | None = _ppid_from_proc(pid)
if ppid is None:
# proc disappeared between `iterdir()` and `stat` —
# treat as gone, don't flag.
continue
if ppid == 1 or ppid in seen:
strays.append(pid) strays.append(pid)
return sorted(strays) return sorted(strays)