Skip to content

Commit 2d59cc8

Browse files
author
Funan Zhou
committed
fix: handle pytest.exit with non-zero exit codes properly
Issue #1239: pytest.exit() with non-zero exit code caused INTERNALERROR in xdist. The assertion 'assert not crashitem' failed because the scheduler had pending tests when the worker exited. Changes: - Handle non-zero exit statuses (other than 2) similarly to keyboard-interrupt - Worker exits with custom exit codes now trigger shouldstop and proper shutdown - Add test case to verify INTERNALERROR is not raised Note: The session exit status is INTERRUPTED (2) due to shouldstop handling, but the fix prevents INTERNALERROR which was the main issue.
1 parent 1bda84e commit 2d59cc8

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

src/xdist/dsession.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,15 @@ def worker_workerfinished(self, node: WorkerController) -> None:
199199
workerready before shutdown was triggered.
200200
"""
201201
self.config.hook.pytest_testnodedown(node=node, error=None)
202-
if node.workeroutput["exitstatus"] == 2: # keyboard-interrupt
202+
exitstatus = node.workeroutput["exitstatus"]
203+
if exitstatus == 2: # keyboard-interrupt
203204
self.shouldstop = f"{node} received keyboard-interrupt"
204205
self.worker_errordown(node, "keyboard-interrupt")
205206
return
207+
if exitstatus != 0: # non-zero exit (pytest.exit with custom returncode)
208+
self.shouldstop = f"{node} exited with status {exitstatus}"
209+
self.worker_errordown(node, f"exit-{exitstatus}")
210+
return
206211
shouldfail = node.workeroutput["shouldfail"]
207212
shouldstop = node.workeroutput["shouldstop"]
208213
for shouldx in [shouldfail, shouldstop]:

testing/acceptance_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,3 +1699,28 @@ def test():
16991699
)
17001700
result = pytester.runpytest()
17011701
assert result.ret == 0
1702+
1703+
1704+
def test_pytest_exit_nonzero_exitcode(pytester: pytest.Pytester) -> None:
1705+
"""Test that pytest.exit() with non-zero exit code is handled properly.
1706+
1707+
Issue #1239: pytest.exit causes internal error when exit code is non-zero.
1708+
"""
1709+
pytester.makepyfile(
1710+
"""
1711+
import pytest
1712+
import time
1713+
1714+
@pytest.mark.parametrize('i', range(10))
1715+
def test_me(i):
1716+
if i == 5:
1717+
pytest.exit("Something", 1)
1718+
time.sleep(0.1)
1719+
"""
1720+
)
1721+
result = pytester.runpytest("-n2", "--tb=short")
1722+
# Should not cause INTERNALERROR, should exit cleanly
1723+
assert "INTERNALERROR" not in result.stdout.str()
1724+
# The worker exit status is handled, but xdist raises Interrupted
1725+
# which causes INTERRUPTED (2) exit status
1726+
assert result.ret == 2 # INTERRUPTED due to shouldstop handling

0 commit comments

Comments
 (0)