Skip to content

Commit a69e830

Browse files
wshallwshallwshallwshallclaude
authored
fix(test): the prune-merged suite's subprocess waits outlive the leg's own pytest timeout (#606)
Every subprocess wait in tests/test_worktree_prune_merged.py is longer than the `repo harness tests` leg's `--timeout=120`: 300 s at the shared `run`/`run_text` helpers and 180 s at two tests. The file carried NO timeout marker at all. When a wait outlives the pytest timeout, pytest-timeout dumps the stacks and calls os._exit(1) -- which kills the xdist worker before execnet can relay the dump. It surfaces as `worker 'gwN' crashed` with no traceback, no captured stdout and no timeout stack, which reads like a native crash and is not one. That diagnosis is not mine: a824cc7 established it and gave tests/test_session_mail.py the identical treatment for the identical signature. MODULE-LEVEL, AND THAT DEPARTS FROM THE PRECEDENT'S PER-TEST SHAPE ON PURPOSE. Two of the four deadlines are in the shared helpers rather than in tests, and 74 of the 75 tests reach them. Seventy-four individual markers would carry no information. The precedent's file had four slow tests among many, which is why per-test was right there; what transfers is its PRINCIPLE -- the marker must outlive the subprocess wait -- not its form. 360 s, NOT the precedent's 300. Its 300 sat against a 240 s maximum wait, i.e. 60 s of headroom. THIS file's maximum wait IS 300, so reusing the number would set the marker equal to the wait and race it. The margin is what was copied, not the figure. The file already carried a pytestmark (a skipif), so it is now a list of two. Verified with pytest's own collector rather than assuming the list form applies: the collected item reports MARKS ['skipif', 'timeout', 'tooling'] timeout_args=[(360,)]. A pytestmark that silently failed to apply would leave a green run, an unchanged flake, and a commit claiming to fix it. PROVENANCE OF THE NUMBERS, because two different people measured them. MINE, verified here: the absent markers; the 300/300/180/180 deadlines and their line numbers; that two of them sit in shared helpers; the 74-of-75 reach count; the precedent's 60 s headroom against its own 240 s maximum; that the precedent cites a PR and no backlog item; the collected marks; and 79 passed locally in 245 s. THE DISPATCHER'S, NOT INDEPENDENTLY VERIFIED BY ME: this signature failed 26.4 percent of `repo harness tests (windows-2025)` job attempts over 08-23 to 08-25, against 6.6 percent the prior week, across 1,174 completed CI-workflow runs -- reproduced to two decimals by a second instrument on their side. Their census also states its own floor: nothing before 08-11, 26 runs still in flight, passing-job logs unread, 22 other workflows not scanned. I am carrying those figures as theirs rather than restating them as measurements of mine. No backlog number allocated, following the precedent in process as well as in shape: a824cc7 landed as a direct fix citing a PR, with no row. The ledger gate rejects a number you did not allocate; it does not require one. Co-authored-by: wshallwshall <mefordev@messagefoundry.org> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent ae25591 commit a69e830

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

tests/test_worktree_prune_merged.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,27 @@
5050

5151
SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "worktree" / "prune-merged.ps1"
5252

53-
pytestmark = pytest.mark.skipif(
54-
shutil.which("pwsh") is None or os.name != "nt",
55-
reason="prune-merged.ps1 needs pwsh on Windows (Process.StartTime liveness fence)",
56-
)
53+
# TWO marks, and the timeout one is load-bearing on CI. Every subprocess wait in this file outlives
54+
# the leg's own `--timeout=120`: 300 s at the `run`/`run_text` helpers and 180 s at two tests. When a
55+
# wait outlives the pytest timeout, pytest-timeout dumps the stacks and calls `os._exit(1)`, which
56+
# kills the xdist worker before execnet can relay the dump -- so it surfaces as `worker 'gwN' crashed`
57+
# with NO traceback and reads like a native crash. Precedent and full diagnosis: a824cc749, which gave
58+
# tests/test_session_mail.py the same treatment for the same signature.
59+
#
60+
# MODULE-LEVEL, DEPARTING FROM THAT PRECEDENT'S PER-TEST SHAPE, and the reason is measured: 74 of the
61+
# 75 tests here reach the 300 s helpers, so 74 individual markers would be noise carrying no
62+
# information. The precedent's file had four slow tests among many, which is why per-test was right
63+
# THERE. Its PRINCIPLE -- the marker must outlive the subprocess wait -- is what transfers.
64+
#
65+
# 360 s is the precedent's headroom, not a guess: it used timeout(300) against a 240 s maximum wait,
66+
# i.e. 60 s of margin. This file's maximum wait is 300 s, so 360 keeps the same margin.
67+
pytestmark = [
68+
pytest.mark.skipif(
69+
shutil.which("pwsh") is None or os.name != "nt",
70+
reason="prune-merged.ps1 needs pwsh on Windows (Process.StartTime liveness fence)",
71+
),
72+
pytest.mark.timeout(360),
73+
]
5774

5875
# Metadata files the activity signal reads. Backdating these is how a fixture gets past the veto
5976
# without turning it off.

0 commit comments

Comments
 (0)