From 01ce2857ea148e987d518968d7b9b143e1f3cad8 Mon Sep 17 00:00:00 2001 From: goodboy Date: Wed, 13 May 2026 19:59:36 -0400 Subject: [PATCH] Add init-adopted orphan reap to `reap_subactors_per_test` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Post-yield now also reaps init-adopted (`ppid==1`) tractor procs that appeared during the test — leaked subactors whose mid-tier parent died during cascade teardown, reparenting them to init. Pre-yield snapshot of existing orphans scopes reap to THIS test's leaks only, avoiding reap of unrelated tractor uses (piker, etc.) on the box. (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- tractor/_testing/_reap.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tractor/_testing/_reap.py b/tractor/_testing/_reap.py index 26d95ec6..96ce3c70 100644 --- a/tractor/_testing/_reap.py +++ b/tractor/_testing/_reap.py @@ -1155,6 +1155,19 @@ def reap_subactors_per_test() -> int: (`_reap_orphaned_subactors`) only kicks in at session end which is too late to save the cascade. + Reaps both: + 1. direct descendants of `pytest` (`PPid==pytest_pid`) + 2. NEW init-adopted tractor procs (`PPid==1` AND + `_is_tractor_subactor`) that appeared between + pre-yield and post-yield — these are the leaked + subactors whose mid-tier parent died during the + cascade, reparenting them to init. + + Pre-yield snapshot of init-adopted tractor procs is + used to scope (2) to THIS test's leaks only — without + it we'd also reap orphans from concurrent unrelated + tractor uses on the box (piker, etc.). + Apply at module-level on the topically-problematic test files via: @@ -1174,7 +1187,16 @@ def reap_subactors_per_test() -> int: ''' parent_pid: int = os.getpid() + # Snapshot pre-existing init-adopted tractor procs so + # we can scope post-test reap to NEW orphans only. + pre_orphans: set[int] = set(find_orphans()) yield parent_pid pids: list[int] = find_descendants(parent_pid) + new_orphans: list[int] = [ + pid for pid in find_orphans() + if pid not in pre_orphans + ] + if new_orphans: + pids.extend(new_orphans) if pids: reap(pids, grace=3.0)