fix: graceful shutdown for subcontainer daemons

Two issues fixed:

1. Process group cascade: exec-command processes inherited the
   container runtime's process group. When an entrypoint script
   did kill(0, SIGTERM) during shutdown, it signaled ALL processes
   in the group — including other subcontainers' launch wrappers,
   causing their PID namespaces to collapse. Fixed by calling
   setsid() in exec-command's pre_exec to isolate each service
   in its own process group.

2. Unordered daemon termination: removeChild("main") fired
   onLeaveContext callbacks for all Daemon.of() instances
   simultaneously, bypassing Daemons.term()'s reverse-dependency
   ordering. Fixed by having Daemons.build() mark individual
   daemons as managed (suppressing their onLeaveContext) and
   registering a single onLeaveContext that calls the ordered
   Daemons.term(). The term() method is deduplicated so
   system.stop() and onLeaveContext share the same shutdown.
This commit is contained in:
Aiden McClelland
2026-03-21 18:19:41 -06:00
parent bdfa918a33
commit 456c5d6725
3 changed files with 30 additions and 2 deletions

View File

@@ -283,6 +283,10 @@ impl ExecParams {
let set_gid = gid.ok();
unsafe {
cmd.pre_exec(move || {
// Create a new process group so entrypoint scripts that do
// kill(0, SIGTERM) don't cascade to other subcontainers.
nix::unistd::setsid()
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
if !groups.is_empty() {
nix::unistd::setgroups(&groups)
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;