From a6d4ac3aacd62c296d532406f185b6dc2ea3537d Mon Sep 17 00:00:00 2001 From: goodboy Date: Thu, 14 May 2026 12:39:33 -0400 Subject: [PATCH] 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 --- tractor/_testing/trace.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tractor/_testing/trace.py b/tractor/_testing/trace.py index 609f00ff..6cc61914 100644 --- a/tractor/_testing/trace.py +++ b/tractor/_testing/trace.py @@ -224,7 +224,19 @@ def _find_tractor_strays(seen: set[int]) -> list[int]: ''' Scan `/proc/*/cmdline` (+ `/comm` as zombie-safe fallback) for `tractor._child` / `tractor[]` 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 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) if pid in seen: 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) return sorted(strays)