fix: set SO_REUSEADDR on port pre-check so restarts don't wait for TIME_WAIT #16

Merged
Pakobbix merged 1 commits from fix/reuseaddr-port-check into main 2026-10-03 19:18:59 +00:00
Collaborator

Problem

Restarting the webui/daemon always required waiting ~1 minute: the fail-fast port pre-check in server.py bound a plain socket without SO_REUSEADDR, so TIME_WAIT sockets left by a just-stopped instance made it report "port already in use" — even though uvicorn (which sets SO_REUSEADDR itself, for both asyncio and uvloop) would have bound fine.

Fix

Set SO_REUSEADDR on the pre-check socket, mirroring uvicorn's actual bind semantics. The check now only fails when the port is genuinely held by a live listener (on Linux, SO_REUSEADDR does not permit two live listeners — that requires SO_REUSEPORT), so fail-fast behavior is preserved.

Verification

  • Reproduced the scenario: with a TIME_WAIT socket on the port, the old check fails (EADDRINUSE), the new check binds OK
  • A live listener on the port is still correctly rejected (no false negatives)
  • Full test suite: 191 passed, 0 failed
## Problem Restarting the webui/daemon always required waiting ~1 minute: the fail-fast port pre-check in `server.py` bound a plain socket without `SO_REUSEADDR`, so `TIME_WAIT` sockets left by a just-stopped instance made it report "port already in use" — even though uvicorn (which sets `SO_REUSEADDR` itself, for both asyncio and uvloop) would have bound fine. ## Fix Set `SO_REUSEADDR` on the pre-check socket, mirroring uvicorn's actual bind semantics. The check now only fails when the port is genuinely held by a live listener (on Linux, `SO_REUSEADDR` does not permit two live listeners — that requires `SO_REUSEPORT`), so fail-fast behavior is preserved. ## Verification - Reproduced the scenario: with a `TIME_WAIT` socket on the port, the old check fails (`EADDRINUSE`), the new check binds OK - A live listener on the port is still correctly rejected (no false negatives) - Full test suite: 191 passed, 0 failed
ARIA added 1 commit 2026-10-03 19:18:29 +00:00
The fail-fast port check bound a plain socket, so TIME_WAIT sockets left
by a just-stopped instance (~60s) made it report 'port already in use'
even though uvicorn (which sets SO_REUSEADDR) could bind fine. Mirror
uvicorn's bind semantics: the check now only fails when the port is
genuinely held by a live listener.
Pakobbix merged commit 92356d1409 into main 2026-10-03 19:18:59 +00:00
Pakobbix deleted branch fix/reuseaddr-port-check 2026-10-03 19:19:00 +00:00
Sign in to join this conversation.