Files
tty7/crates/tty7-server
l0ng-aiandl0ng-ai 0df604054d fix(daemon): keep a lingering daemon findable and reapable after quit-and-stop (#655)
* fix(daemon): keep a lingering daemon findable and reapable after quit-and-stop

Quit-and-stop could strand a daemon that had already unlinked daemon.sock
and deleted daemon.pid but never finished exiting: libc exit() runs atexit
handlers and static destructors beside dozens of live threads, and a
finalizer that blocks leaves the process holding the singleton lock with no
name on disk. Every later launch then spawns a daemon that stands down
against the lock and times out red, forever.

Three changes, each a fallback for the others:

- on_shutdown keeps the pidfile: once the endpoint is unlinked it is the
  only handle anything has on a process that is not gone yet. A pidfile
  that outlives a clean exit was already handled by recorded_daemon_is_dead
  and the reap path.
- The daemon exits through _exit(2) (after flushing the logger), skipping
  the atexit/destructor window entirely; everything owed to disk is flushed
  explicitly in on_shutdown.
- spawn::stop reaps with the pid it captured before asking the daemon to
  die, instead of re-reading a pidfile an old build's shutdown may have
  wiped mid-stop; reap_recorded_daemon keeps the pidfile when the process
  survives even SIGKILL, so the next attempt still has someone to reap.

* review: fix stale stop() comment, pin the mid-stop pidfile-vanish ordering in the test

The comment at the top of stop() still claimed a clean shutdown removes
the pidfile, which this branch just made untrue; it now states the real
reasons the pid is captured early. The vanishing-pidfile test now asserts
the sweeper's delete actually landed while stop() was waiting, so a
future shrink of PROCESS_EXIT_TIMEOUT cannot silently turn it into a
weaker scenario.

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-08-16 17:35:39 +08:00
..