Background mode without a tray icon is a resident process nobody can see
or quit. When the tray was requested but failed to start, take both
switches back out of the host’s environment, whether they came from the
launcher’s own env (the setting) or from --background. Must run after
every .env/.envs that could set them: later Command env calls win.
The signal itself goes through agentmux_common::process::signal_process_group,
which refuses a pgid of 0 or 1 (the launcher’s own group, or the
broadcast) rather than signalling it.
Send signal to an entire process group in one shot (negated pid — see
the two public wrappers below for why this targets a whole group, not
just one process). Shared by both so the return-value handling — a
silently-ignored failure would otherwise let a genuinely-failed kill
(anything but the expected “already empty” ESRCH) read as a successful
teardown — lives in exactly one place. Logs on any failure OTHER than
ESRCH (the routine no-op case: the group was already empty, e.g. a prior
SIGTERM’s own graceful shutdown already reaped it).
SIGKILL an entire process group in one shot — the unix analogue of
Windows’ TerminateJobObject. child must have been spawned with
.process_group(0) (both spawn_host_unix and srv_spawner::spawn_srv
do this) so its pgid equals its own pid; negating the pid targets the
whole group instead of just the one process, reaping any descendants
(e.g. CEF’s forked renderer/GPU subprocesses) the launcher never tracks
individually. Used by the teardown backstop
(SPEC_LAUNCHER_TEARDOWN_BACKSTOP_2026_07_11) as the hard backstop after
kill_process_group_gracefully’s brief grace window — reserved for
whatever a graceful SIGTERM didn’t reap (a wedged-or-dead srv, or shells
its own stop_all() couldn’t finish in time). No-op if the child has
already exited (its pid may have been reaped; a stale pid’s negated kill
returns ESRCH, ignored).
SIGTERM an entire process group, before the harder
kill_process_group_forcefully follows. The teardown backstop uses it
on the host’s group; srv is never group-signalled first, since its own
SIGTERM/stdin-EOF shutdown closes its agents (upgrade::quiesce_srv).
AGENTMUX_LAUNCHER_EXE for the host: this launcher’s own executable, so
the host can invoke launcher CLI verbs (--autostart-status,
--enable-autostart, --disable-autostart) on the user’s behalf. Empty
when current_exe fails — the host then reports auto-start as unavailable.
Spawn the CEF host on Unix with the srv endpoints + canonical
data-dir env handed off, mirroring spawn_host_supervised minus the
Windows-only machinery (Job Object assignment, CREATE_SUSPENDED /
resume, named-pipe handle, splash event). disable_gpu is the retry
ladder’s degraded rung (software rendering). Returns the running
child or None if spawn failed.
Should this host hold its “main” window hidden
(SPEC_START_WITH_OS_2026_09_25.md §3.3)? Only for a login start, only when
the tray is up (no tray means a normal window, never an invisible process),
and only for the first host: a host restarted after a crash must come back
visible, since the user may already have been using it.
Send SIGTERM to a child so it can shut down gracefully — for the CEF
host that means reaping its render subprocesses (a tokio start_kill
SIGKILL would orphan them); for srv it’s a clean shutdown. No-op if the
child has already exited (its pid may have been reaped). Best-effort:
the SIGKILL grace-window backstop in run_unix catches anything that
ignores SIGTERM.