Skip to content

fix: stop worker when shouldfail/shouldstop is set (--exitfirst / --maxfail)#1338

Open
goingforstudying-ctrl wants to merge 2 commits into
pytest-dev:masterfrom
goingforstudying-ctrl:fix/exitfirst-shouldfail-worker-stop
Open

fix: stop worker when shouldfail/shouldstop is set (--exitfirst / --maxfail)#1338
goingforstudying-ctrl wants to merge 2 commits into
pytest-dev:masterfrom
goingforstudying-ctrl:fix/exitfirst-shouldfail-worker-stop

Conversation

@goingforstudying-ctrl

Copy link
Copy Markdown

The --exitfirst / --maxfail flags don't stop workers promptly when a test fails. The failing worker keeps running — it executes the next pre-fetched test before checking shouldfail.

Turns out the issue is in the worker's main loop: torun.get() pre-fetches the NEXT test before the current one finishes. When the current test fails, session.shouldfail gets set by pytest's runner. But run_one_test already moved on — the pre-fetched item is about to execute and the shouldfail check after run_one_test comes too late.

Noticed this while looking at #420 (open since 2019), #868, and #1034 — they all point to the same underlying thing.

What this does:

  1. Checks shouldfail/shouldstop before run_one_test in the while loop, so a locally-set flag from the previous iteration is caught
  2. After runtest_protocol_complete, if shouldfail/shouldstop is truthy, overrides nextitem_index to Marker.SHUTDOWN — this makes the loop exit cleanly without running the already-fetched next item

With -x set, the worker that hits a failure now stops right after the failing test instead of running one more.

Happy to adjust the approach if there's a better place to hook this.

goingforstudying-ctrl added 2 commits June 16, 2026 00:38
When --exitfirst or --maxfail is used with pytest-xdist, the worker
pre-fetches the next test via torun.get() inside run_one_test before
the current test finishes. If the current test fails, pytest sets
session.shouldfail, but the pre-fetched test still runs because the
check happens AFTER run_one_test completes, not before.

Add a shouldfail/shouldstop check in the while loop before calling
run_one_test to catch the flag set during the previous iteration.
Additionally, after sending runtest_protocol_complete, overwrite
nextitem_index to Marker.SHUTDOWN so the while loop exits cleanly
without executing the pre-fetched test.

Fixes pytest-dev#420
Fixes pytest-dev#868
Fixes pytest-dev#1034
The shouldfail/shouldstop check inside run_one_test() already sets
nextitem_index to Marker.SHUTDOWN when the flags are set, causing the
while loop to exit naturally. The duplicate break after run_one_test()
is unreachable and triggers a mypy error.

Signed-off-by: goingforstudying-ctrl <goingforstudying-ctrl@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant