From 4bebcafddec2bd9c860fcf26e0db59d7a4c930a7 Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Wed, 25 Mar 2026 10:31:29 -0600 Subject: [PATCH] fix: tolerate setsid EPERM in subcontainer pre_exec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In TTY mode, pty_process already calls setsid() on the child before our pre_exec runs. The second setsid() fails with EPERM since the process is already a session leader. This is harmless — ignore it. --- core/src/service/effects/subcontainer/sync.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/service/effects/subcontainer/sync.rs b/core/src/service/effects/subcontainer/sync.rs index e1cb07bfe..359888653 100644 --- a/core/src/service/effects/subcontainer/sync.rs +++ b/core/src/service/effects/subcontainer/sync.rs @@ -283,10 +283,16 @@ impl ExecParams { let set_gid = gid.ok(); unsafe { cmd.pre_exec(move || { - // Create a new process group so entrypoint scripts that do + // Create a new session 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))?; + // EPERM means we're already a session leader (e.g. pty_process + // called setsid() for us), which is fine. + match nix::unistd::setsid() { + Ok(_) | Err(Errno::EPERM) => {} + Err(e) => { + return Err(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))?;