Repository navigation
Stop other workers promptly when --maxfail/-x is reached - #1395
RonnyPfannschmidt wants to merge 5 commits into
Conversation
Previously the controller's shutdown command was queued behind the tests already sent to each worker, so other workers kept running their whole queue after the first failure. Now the controller sends shutdown(immediately=True) when stopping early, and workers break out after their current test. Fixes #420 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S74uNrKyts6p5C9Mci4CmV
|
🤖 Written by Claude Opus 5.5 via Claude Code for the pytest-xdist maintainers; I prompted it, it did the work, I read it.
Update: resolved. |
Setting shouldstop on the worker also makes the controller skip the pending-items crash check in worker_workerfinished, so that special case is no longer needed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S74uNrKyts6p5C9Mci4CmV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S74uNrKyts6p5C9Mci4CmV
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Workers can still start an unstarted test after receiving shutdown during lookahead or ramp-up waits.
Review effort: Balanced
Findings: 1
Open (1)
What changed in this PR
Addresses #420 by forwarding stop reasons to workers so they can stop without draining queued tests.
Changes:
- Propagates controller stop reasons through shutdown commands.
- Adds an acceptance test for stopping other workers.
- Updates the test double and changelog.
| File | Description |
|---|---|
| testing/test_dsession.py | Updates the shutdown test double’s signature. |
| testing/acceptance_test.py | Tests early stopping across workers. |
| src/xdist/workermanage.py | Includes stop reasons in shutdown commands. |
| src/xdist/remote.py | Sets the worker session’s stop flag. |
| src/xdist/dsession.py | Forwards the controller’s stop reason. |
| changelog/420.bugfix.rst | Documents the early-stop behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The worker can receive the controller's shutdown while blocked on the lookahead get() or during the --ramp delay; check shouldstop again before running the protocol. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S74uNrKyts6p5C9Mci4CmV

Requested by Ronny · project thread
🤖 Written by Claude Opus 5.5 via Claude Code for the pytest-xdist maintainers; I prompted it, it did the work, I read it.
Fixes #420.
Before: when
-x/--maxfailis reached, the worker that hit the failure stops (since #1024), but every other worker keeps running all tests already queued to it. The controller'sshutdowncommand only appends a stop marker to the end of each worker's queue.After: the other workers stop after the test they are currently running, and do not start a new one.
How:
triggershutdownpasses the controller'sshouldstopvalue (e.g. "stopping after 1 failures", or a keyboard-interrupt reason) along with theshutdowncommand. When it is set, the worker assigns it tosession.shouldstop. The run loop already checks that after each test, andrun_one_testnow also checks it after waiting for the next item or the--rampdelay, so a stop that arrives during those waits doesn't start another test. Final teardown still happens inpytest_sessionfinishas with plainpytest -x. Because the worker reportsshouldstopback, the controller's existing path inworker_workerfinishedskips the pending-items crash check, so no special case is needed there. Plainshutdownsent by the schedulers when nothing is left to distribute is unchanged.Limitation: tests that already started before the stop command arrives still run to completion.
test_maxfail_stops_other_workers(--dist=loadfile, 40 slow tests on the other worker): 40 pass without the fix, fewer than 20 with it.test_maxfail_stops_worker_during_ramp(-x -n2 --ramp=3): the delayed worker ran 1 test without the fix, 0 with it.changelog/420.bugfix.rstNote: the
TestLoadScope::test_workqueue_ordered_by_*tests are intermittently failing under full-suite load on master as well; unrelated to this change.🤖 Generated with Claude Code
https://claude.ai/code/session_01S74uNrKyts6p5C9Mci4CmV