bug(infinity-daemon): daemon restart leaves stale pid/socket files behind on failed startup; daemon never recovers without manual cleanup
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
Research direction
Start by locating the infinity-daemon startup and stop/restart entry points, then trace where TCP binding and daemon.log, daemon.sock, and daemon.pid changes occur. Reproduce the stated stale-pid scenario and inspect the existing daemon tests. Done means a failed startup leaves the running daemon’s management files and log intact, and stop/restart detect stale or mismatched daemon state without spawning a competing daemon.
Written by the indexing model from the issue text.
Description
Summary
When a daemon start fails partway (e.g. TCP port already bound), the failed run has already truncated daemon.log, replaced daemon.sock, and rewritten daemon.pid with its own (now dead) PID. From then on the installation is wedged: restart/stop trust the dead pidfile, new unix-socket clients get ECONNREFUSED, and the previously-running daemon is orphaned from management. Nothing heals itself; recovery today requires manually killing leftovers and deleting the files. The daemon should clean up after a failed start and verify liveness beyond the pidfile.
Environment
- macOS (Darwin arm64)
- infinity --version reports infinity-agent-cli 0.2.0
- ~/.infinity/providers.json / ~/.infinity/rap.json configured with providers, sandbox, rap, and mcp
What I observed
- A running daemon (PID 79449, up since 08:12) with both model providers serving.
- ~/.infinity/daemon.pid contained 79814 — no such process.
- ~/.infinity/daemon.sock dated 08:32 (20 min after the daemon started). Raw connect() to it → ECONNREFUSED.
- infinity daemon restart → daemon is not running — starting a fresh one → Error: daemon exited during startup (exit status: 1) / Address already in use (os error 48) — the live daemon still held the TCP port.
- daemon.log was 0 bytes (truncated at 08:32), and stayed empty — all forensic evidence of whatever happened was wiped by the failed start.
Manual recovery (what I had to do): kill the leftover daemon + orphaned provider processes, delete the stale socket/pidfile, infinity daemon restart — after which pidfile matched the new PID, both providers served, unix socket connected, and websocket Welcome arrived with the connection staying open.
Repro (deterministic, no crash needed)
infinity daemon restart # healthy daemon A running, pidfile=A
echo 999999 > ~/.infinity/daemon.pid # simulate pid desync
infinity daemon restart
# → "daemon is not running — starting a fresh one"
# → new daemon B truncates daemon.log, recreates daemon.sock,
# writes pidfile=B, then dies on TCP bind (A still holds it)
# End state: socket file + pidfile belong to dead B; clients get
# ECONNREFUSED; daemon A is orphaned from `stop`/`restart`;
# pre-existing log content is gone.
Suggested behavior
- Bind first, mutate files second. On startup, attempt the TCP bind (and any other exclusive resource) before truncating daemon.log or replacing daemon.sock / daemon.pid. If the port is taken, abort with another daemon appears to be running and touch nothing.
- Don't leave corpses on failed startup. If the daemon exits during startup after creating files, remove the ones it created (at minimum a pidfile pointing at a PID that will never live again).
- Verify liveness, not just pid existence. stop/restart should confirm the pidfile PID is actually this daemon (e.g. kill(pid, 0) plus a command-line check, or better: probe the socket/port it should hold) and say plainly when management state and reality disagree, instead of "not running" → spawning a rival.
- Consider single-instance locking (e.g. flock on a lock file in ~/.infinity) so a second daemon can never clobber the first's files.
Related observation (separate, possibly its own issue)
daemon.log is truncated on every (re)start, including failed starts — which is what erased the evidence here. Log rotation (daemon.log.1) or append-only startup would preserve crash forensics. Happy to file separately if you prefer.
- Dominant language
- Rust
- Stars
- 716
- Forks
- 81
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 11
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from hydro-project/infinity
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
hydro-project/infinity#189 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
hydro-project/infinity#187 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
hydro-project/infinity#174 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 43/100
hydro-project/infinity#186 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
hydro-project/infinity#177 ·
Maintainers usually reply within 1 day
All issues in hydro-project/infinity
Similar issues
-
binding:python bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
coollabsio/orbit#72 ·
Maintainers usually reply within 1 day
-
Synth suite fails unless run from the repo root: signal_flow's default machine path is cwd-relativeOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
Nimblesite/osprey#370 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
bug order-flow studies ui
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
userFRM/egui-charts#2417 ·
Maintainers usually reply within 1 day