Expand description
Reclaim the data dir from an srv that an earlier launcher left behind.
srv takes an exclusive flock on <data_dir>/srv.lock and writes its PID
into it (crates/srv/src/backend/base.rs, acquire_data_dir_lock). If an
srv outlives its launcher, every later launch’s srv fails on that lock and
the app cannot be opened (2026-10-11: macOS “Quit & Reopen” left one
behind). An srv still holding the lock whose launcher is gone (it was
reparented to launchd/init) is stale: stop it, and start fresh.
Only a process that is an agentmux-srv binary is stopped, and never one
started headless (--headless / AGENTMUX_HEADLESS=1), which runs on its
own by design, and never one whose parent is still an AgentMux launcher:
winning the single-instance socket isn’t proof enough on its own, since two
local builds of one checkout can share a data dir with different sockets.
Constants§
- SRV_
LOCK_ 🔒FILE - Name of srv’s data-dir lock file. Mirrors
SRV_DATA_LOCK_FILEincrates/srv/src/backend/base.rs. - TERM_
GRACE 🔒 - How long a stale srv gets to exit after SIGTERM (it closes its agents first) before its whole process group is killed.
Functions§
- lock_
holder_ 🔒via_ lsof - The process that has
lock_pathopen, for a lock file without a recorded PID: an agentmux-srv among the holders if there is one, else the first. The checks inreclaim_stale_srv_lockstill apply to it. - lock_
is_ 🔒free - True when nobody holds the lock (or the file doesn’t exist). Takes and immediately releases the lock; the srv spawned next takes it for real.
- processes_
with_ 🔒file_ open - PIDs with
pathopen. Linux: read/proc/<pid>/fddirectly, sincelsofisn’t installed everywhere (the AppImage doesn’t bundle it and the packages declare no dependencies). Only this user’s processes are readable, which is all an srv we could stop can be. - ps_
field 🔒 - One
psfield forpid(ww: untruncated;with_env: append the process’ environment,ps e), orNoneif it isn’t running. Never log the result: it can hold another process’ secrets. - reclaim_
stale_ srv_ lock - If
<data_dir>/srv.lockis held, stop the stale srv holding it. Returns once the lock is free, or the holder can’t be stopped (the srv spawn that follows then fails and reports it as before). - wait_
for_ 🔒free