From 26db26e416318e17a6e7f3f196ec72109fb37998 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Tue, 30 Jun 2026 19:48:56 +0300 Subject: fix: keep remote sessions alive across disconnects --- src/server/autodetect.rs | 27 +++++++++++++++++++-------- src/server/handoff.rs | 4 +--- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src/server') diff --git a/src/server/autodetect.rs b/src/server/autodetect.rs index f40be988..0c9e0cde 100644 --- a/src/server/autodetect.rs +++ b/src/server/autodetect.rs @@ -9,8 +9,6 @@ //! (escape hatch for users who want the traditional single-process behavior). use std::io; -#[cfg(unix)] -use std::os::unix::process::CommandExt; use std::path::Path; use std::path::PathBuf; use std::process::Command; @@ -218,12 +216,7 @@ fn build_server_daemon_command(exe: PathBuf) -> Command { .stdin(std::process::Stdio::null()) .stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()); - #[cfg(unix)] - { - // Create a new process group so the server survives the parent's exit - // and doesn't receive SIGHUP when the client's terminal closes. - command.process_group(0); - } + crate::platform::detach_server_daemon_command(&mut command); match std::env::current_dir() { Ok(cwd) => { @@ -384,6 +377,24 @@ mod tests { })); } + #[cfg(target_os = "linux")] + #[test] + fn server_daemon_detach_creates_new_session() { + let mut command = Command::new("sh"); + command.arg("-c").arg( + r#"sid=$(ps -o sid= -p $$ | tr -d ' ') +test "$sid" = "$$" +"#, + ); + crate::platform::detach_server_daemon_command(&mut command); + + let status = command.status().unwrap(); + assert!( + status.success(), + "detached server child should be its own session leader" + ); + } + #[test] fn is_server_listening_returns_true_for_live_socket() { let dir = unique_test_dir("live"); diff --git a/src/server/handoff.rs b/src/server/handoff.rs index 816537ab..2be36c2a 100644 --- a/src/server/handoff.rs +++ b/src/server/handoff.rs @@ -5,8 +5,6 @@ use std::os::fd::{AsRawFd, RawFd}; #[cfg(unix)] use std::os::unix::net::{UnixListener, UnixStream}; #[cfg(unix)] -use std::os::unix::process::CommandExt; -#[cfg(unix)] use std::path::{Path, PathBuf}; #[cfg(unix)] use std::process::{Child, Command}; @@ -79,10 +77,10 @@ pub(crate) fn spawn_handoff_import( .arg("--handoff-import") .arg(socket_path) .arg(token) - .process_group(0) .stdin(std::process::Stdio::null()) .stdout(std::process::Stdio::null()) .stderr(std::process::Stdio::null()); + crate::platform::detach_server_daemon_command(&mut command); command.spawn().map_err(|err| { io::Error::new( err.kind(), -- cgit v1.2.3