Repository navigation
Conversation
openviking-server bound its listen socket inside uvicorn.run, which logs a bind failure and exits gracefully — so a supervised restart (watchdog, systemd Restart=always, Docker healthcheck) racing the old process winding down killed the new process on the first EADDRINUSE. Bind the socket up front instead, retrying while the port is held (server.bind_retry_attempts, default 5; server.bind_retry_interval_ seconds, default 1.0; 0 attempts keeps the die-immediately behavior), then hand it to uvicorn: Server.run(sockets=[...]) for the single process path, and the inherited fd= for the multi-worker path, since uvicorn 0.41's run()/Config take no sock parameter. Verified live: port held -> 'still in use (attempt n/8)' retries -> holder released -> /health 200; port held forever -> retries exhaust -> original OSError; free port -> unchanged startup. Fixes volcengine#5401 Co-Authored-By: Claude Code <noreply@anthropic.com>
Upstream's remote-restart recovery replaced the single-worker _run_uvicorn call with _run_restartable_server. Keep both semantics: bind the socket up front with the bounded EADDRINUSE retry, then hand the pre-bound socket to the restartable server via uvicorn's sock= config (dropping host/port, which a bound socket supersedes).
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
openviking-serverbound its listen socket insideuvicorn.run, which logs a bind failure and exits gracefully — so a supervised restart (watchdog, systemdRestart=always, Docker healthcheck) racing the old process winding down killed the new process on the firstEADDRINUSE.The socket is now bound up front, retrying while the port is held (
server.bind_retry_attempts, default 5;server.bind_retry_interval_seconds, default 1.0;0attempts keeps the die-immediately behavior), and then handed to uvicorn:Server.run(sockets=[...])for the single-process path, and the inheritedfd=for the multi-worker path, since uvicorn 0.41'srun()/Configtake nosockparameter andrun()swallows the bind error instead of raising.Human Involvement
Related Issue
Fixes #5401
Type of Change
Changes Made
openviking/server/bootstrap.py:_bind_socket_with_retry(bounded EADDRINUSE retries with a stderr note per attempt) +_run_uvicornhanding the pre-bound socket to uvicorn per mode; both startup call sites routed through it.openviking/server/config.py:server.bind_retry_attempts/server.bind_retry_interval_secondswith the rationale in the field description.tests/server/test_bootstrap_bind_retry.py: real-socket tests for the waited-out holder, exhausted retries (original OSError semantics), zero-attempts fail-fast, free-port no-retry, and conservative defaults.Testing
pytest tests/server/test_bootstrap_bind_retry.py: 6/6 pass;ruff checkclean./health200; port held forever → retries exhaust → original OSError; free port → unchanged startup.🤖 Generated with Claude Code