fix(lease-broker): wait_ready() polls real connect-readiness not socket-file existence (flaky CI race)
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful

setUp() spawned the daemon and polled only for the unix-socket file to
exist before proceeding to connect(). Under concurrent CI-runner load
the socket file can appear (created by bind()) before the daemon calls
listen(), so the client's immediate connect() raced ahead and hit
ConnectionRefusedError: [Errno 111], erroring the whole suite in
setUp().

wait_ready() now attempts a real socket.connect() in a retry loop
(catching ConnectionRefusedError/FileNotFoundError) until a connection
actually succeeds (then closes it) or the same 5s deadline elapses,
at which point it fails exactly as before. Readiness is now "the
daemon is actually accepting connections," not "a file happens to
exist," eliminating the TOCTOU race.

Scope: only wait_ready() in this file changed. Zero assertion changes,
zero daemon/lease-broker source changes, zero gate-timeout relaxation.

Closes #897
This commit is contained in:
mosaic-coder
2026-07-25 16:47:42 -05:00
parent 2698ddb7b5
commit 98a20bfaab

View File

@@ -51,8 +51,13 @@ def request(socket_path: Path, value: dict[str, object]) -> dict[str, object]:
def wait_ready(process: subprocess.Popen[str], socket_path: Path) -> None: def wait_ready(process: subprocess.Popen[str], socket_path: Path) -> None:
deadline = time.monotonic() + 5.0 deadline = time.monotonic() + 5.0
while time.monotonic() < deadline: while time.monotonic() < deadline:
if socket_path.exists(): try:
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as probe:
probe.settimeout(0.25)
probe.connect(str(socket_path))
return return
except (ConnectionRefusedError, FileNotFoundError):
pass
if process.poll() is not None: if process.poll() is not None:
output = process.stdout.read() if process.stdout is not None else "" output = process.stdout.read() if process.stdout is not None else ""
raise RuntimeError(f"daemon exited before READY: {output}") raise RuntimeError(f"daemon exited before READY: {output}")