use tokio::process::Command; #[cfg(windows)] const CREATE_NO_WINDOW_FLAG: u32 = 0x08000000; #[cfg(target_os = "linux")] fn configure_parent_death_signal(command: &mut Command) { let parent_pid = unsafe { libc::getpid() }; unsafe { command.pre_exec(move || { if libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) != 0 { return Err(std::io::Error::last_os_error()); } if libc::getppid() != parent_pid { return Err(std::io::Error::from_raw_os_error(libc::ESRCH)); } Ok(()) }); } } pub trait SubprocessExt { fn set_no_window(&mut self) -> &mut Self; } /// Creates a Git command that rejects implicit bare repositories and cannot run a /// repository-configured fsmonitor hook. pub fn git_command() -> std::process::Command { let mut command = std::process::Command::new("git"); command.args([ "-c", "safe.bareRepository=explicit", "-c", "core.fsmonitor=false", ]); command } impl SubprocessExt for Command { fn set_no_window(&mut self) -> &mut Self { #[cfg(windows)] { self.creation_flags(CREATE_NO_WINDOW_FLAG); } self } } impl SubprocessExt for std::process::Command { fn set_no_window(&mut self) -> &mut Self { #[cfg(windows)] { use std::os::windows::process::CommandExt; self.creation_flags(CREATE_NO_WINDOW_FLAG); } self } } #[allow(unused_variables)] pub fn configure_subprocess(command: &mut Command) { // Isolate subprocess into its own process group so it does not receive // SIGINT when the user presses Ctrl+C in the terminal. #[cfg(unix)] command.process_group(0); #[cfg(target_os = "linux")] configure_parent_death_signal(command); command.set_no_window(); }