Skip to main content

Module reexec

Module reexec 

Source
Expand description

A long-lived process follows a reinstall in place: cargo install renames a new file over the old, and an old image would go on running the code it was started with.

  • A session’s waiter (listen.rs) re-execs its own path (Image::reexec), same pid, same stdout (a plugin’s JSON line protocol and Claude Code’s background task survive), its lock’s open file description passed on (ADOPT_FD), so the lock is never free between the images and no second waiter starts meanwhile. SIGINT, SIGHUP and SIGTERM are blocked across the exec and seen by the new image once it trapped them (inherited): none is lost. Its only other threads (runner.rs run_bounded’s readers) start with them blocked too.

The mesh daemon (borg-mesh main.rs serve) follows a reinstall of borg-mesh in place: it lives as long as the machine serves, and cargo install renames a new file over the old. Once its image is stale (Image::due) it stops as on Ctrl-C, and Image::restart execs the new borg-mesh in the same process (trap_stops, stopped: a stop during it is held for the new image, which ends on it before it serves). Only one that says it takes such a restart (probed) is exec’d: one built before it could (a downgrade) would never unblock the stops, so no Ctrl-C or SIGTERM would ever end it. The daemon exits 1 with a message then, to be started again.

The identity is that of the path the process was started by (argv[0] resolved as execvp does), not of /proc/self/exe: a wrapper or shim is the file that is exec’d, so comparing it with the binary it starts would differ forever and re-exec in a loop. A running binary deleted from under a path that stays (a symlinked install whose old target went) counts too: its link count is 0.

Structs§

Image
What a long-lived process’s image was started from (now, at its start): whether it is the binary installed now.

Enums§

ReexecError
Why Image::reexec did not replace the image.

Functions§

adopt
The inherited fd as the lock of path, when it is that file’s open description and holds its lock (a try_lock on the same description succeeds); else None (a forged or stale variable: the waiter takes the lock as a fresh one does). Close-on-exec again from here.
inherited
The first step of a waiter (listen.rs), once it trapped its stop signals: when a previous image re-exec’d it (Image::reexec), the inherited lock fd, its variable gone from the environment, the stop signals unblocked only now, so a stop that came across the exec is seen; None for a fresh start. The fd is the waiter’s lock only once adopt checked it.
on_signals
handler for each of sigs, by sigaction(2): it stays installed across deliveries, and a call it interrupts restarts. handler must be async-signal-safe (store to an atomic, no more).
probed
The first step of a process that may be restarted into (borg-mesh main): true when this run is restart’s probe, answered here (the caller then ends at once).
stopped
Whether a stop came since trap_stops.
trap_stops
The first step of a process that may restart (the mesh daemon), while it runs one thread: SIGINT and SIGTERM trapped (stopped says whether one came), and, when a previous image restarted it, the stop signals unblocked only then, so a stop that came across the exec is seen now (a SIGHUP then ends it, as it would have the old one).