#4114·atuin

[Bug]: daemon `autostart` will not respawn a wedged (alive-but-not-serving) daemon — a live pidfile blocks recovery, freezing every shell command

Author: ericzikoCreated Sep 11, 2026Updated Sep 11, 2026

Version

atuin 18.22.0 (Linux, [daemon] enabled = true, autostart = true).

Summary

autostart decides whether to spawn the daemon from the pidfile alone: if the recorded PID is alive, it assumes a healthy daemon and does nothing. But a daemon process can be alive yet not serving its socket (the socket was removed out from under it, or it stopped listening). In that state autostart never respawns a working daemon, so every interactive command's preexec (atuin history start) keeps hitting a dead/absent socket and blocking — permanently, until manual intervention, not transiently.

This is adjacent to #3382 (client freezes on a non-serving socket), but the root here is specifically that autostart's liveness check is "is the PID alive?" instead of "is the daemon actually reachable?", so the system can't self-heal.

What I observed

  • The daemon PID (recorded in ~/.local/share/atuin/atuin-daemon.pid) was alive, but held no listening socketss -x showed none, and no socket file existed at the expected path.
  • Every command stalled ~4 s in atuin history start. autostart never respawned the daemon because the pidfile PID was still alive.
  • Killing the wedged PID (which made the pidfile stale) let autostart spawn a fresh, healthy daemon on the next atuin invocation, and per-command latency dropped from ~4 s back to ~0.03 s.

Repro

  1. [daemon] enabled = true, autostart = true; let the daemon start.
  2. Put it into an alive-but-not-serving state — e.g. rm its socket file while the process keeps running (in my real-world case a scratch-dir cleaner removed the socket), or otherwise make it stop listening while the PID stays up.
  3. Run any command. atuin history start in preexec blocks; autostart does not respawn a working daemon because the pidfile PID is still alive. The stall persists across every command.

Suggested fix

autostart's health check should confirm the daemon is actually serving (connect to the socket / do a lightweight handshake), not merely that the pidfile PID is alive. If the PID is alive but unreachable, respawn it (or clear the stale pidfile and start fresh) — or at minimum surface an error — instead of assuming healthy. Pairs well with the short client-side connect timeout requested in #3382: a fast timeout stops the freeze, and a serving-not-just-alive check lets the daemon recover on its own.

Workaround

Run the daemon under an external supervisor with autostart = false — e.g. a systemd --user unit with Restart=always and an ExecStartPre that clears a stale socket — so recovery does not depend on autostart's pidfile check.