ITADN

Fix _sock_recv infinite loop when StatusDB TCP connection drops

#322Pull RequestTKeji 创建于 2026-03-30
T
TKejicommented
## Problem When using `--reruns` with `pytest-xdist`, every test makes two blocking TCP calls to the `StatusDB` server (`get_test_failures` and `set_test_reruns` in `pytest_runtest_protocol`). If the server-side connection drops, `_sock_recv` enters an infinite loop: ```python def _sock_recv(self, conn) -> str: buf = b"" while True: b = conn.recv(1) if b == self.delim: # b"" != b"\n" → never breaks break buf += b return buf.decode() ``` `recv(1)` returns `b""` (empty bytes) on a closed socket, but the code only checks for the newline delimiter. Since `b"" != b"\n"` is always `True`, the loop never exits. This causes xdist workers to hang indefinitely at ~90% CPU, appearing stuck on a test that never completes (`[pytest-xdist running] ...`). The hang persists until the process is manually killed. ## Fix Add a check for empty bytes from `recv(1)` and raise `ConnectionError`: ```python b = conn.recv(1) if not b: raise ConnectionError("StatusDB connection closed unexpectedly") ``` The `ConnectionError` propagates as an `INTERNALERROR` that xdist handles by replacing the worker — much better than hanging forever. ## Reproduction **Minimal reproduction** (proves the infinite loop on the unpatched version): ```python import socket from pytest_rerunfailures import SocketDB s1, s2 = socket.socketpair() s2.close() # recv on s1 will now return b"" db = SocketDB() db._sock_recv(s1) # hangs forever on unpatched, raises ConnectionError on patched ``` **Full reproduction in a test run**: monkey-patch `ServerStatusDB.run_connection` to close the server-side connection after a few requests, then run `pytest --reruns=1 -n 1 --dist=loadgroup`. The worker hangs on the next test's `db.get_test_failures()` call in `_sock_recv`. ## Impact Affects any xdist run with `--reruns` enabled. Without `--reruns`, the TCP protocol is never exercised (`pytest_runtest_protocol` returns early), so the bug doesn't manifest. ## Checklist - [x] Changelog entry in `CHANGES.rst` - [x] Test added - [x] Pre-commit hooks pass
合并状态:未合并 1 条评论