Fix _sock_recv infinite loop when StatusDB TCP connection drops
## 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 条评论