From 43e517cea6704f0d8424a88b13a1d40550c7e9ca Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 30 Dec 2021 16:15:14 -0500 Subject: add spawn_pg --- src/blocking/command.rs | 24 ++++++++++++++++++++++++ src/command.rs | 24 ++++++++++++++++++++++++ src/sys.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/src/blocking/command.rs b/src/blocking/command.rs index ed36443..2cbfb97 100644 --- a/src/blocking/command.rs +++ b/src/blocking/command.rs @@ -128,6 +128,30 @@ impl Command { Ok(self.inner.spawn()?) } + pub fn spawn_pg( + &mut self, + pg: Option, + ) -> crate::Result { + let mut set_process_group = crate::sys::set_process_group_child(pg); + // Safety: setpgid() is an async-signal-safe function and ioctl() is a + // raw syscall (which is inherently async-signal-safe). + if let Some(mut custom) = self.pre_exec.take() { + unsafe { + self.inner.pre_exec(move || { + set_process_group()?; + custom()?; + Ok(()) + }) + }; + } else { + unsafe { self.inner.pre_exec(set_process_group) }; + } + + let child = self.inner.spawn()?; + crate::sys::set_process_group_parent(child.id(), pg)?; + Ok(child) + } + pub fn uid(&mut self, id: u32) -> &mut Self { self.inner.uid(id); self diff --git a/src/command.rs b/src/command.rs index cd1c8a3..c6dac9d 100644 --- a/src/command.rs +++ b/src/command.rs @@ -128,6 +128,30 @@ impl Command { Ok(self.inner.spawn()?) } + pub fn spawn_pg( + &mut self, + pg: Option, + ) -> crate::Result { + let mut set_process_group = crate::sys::set_process_group_child(pg); + // Safety: setpgid() is an async-signal-safe function and ioctl() is a + // raw syscall (which is inherently async-signal-safe). + if let Some(mut custom) = self.pre_exec.take() { + unsafe { + self.inner.pre_exec(move || { + set_process_group()?; + custom()?; + Ok(()) + }) + }; + } else { + unsafe { self.inner.pre_exec(set_process_group) }; + } + + let child = self.inner.spawn()?; + crate::sys::set_process_group_parent(child.id(), pg)?; + Ok(child) + } + pub fn uid(&mut self, id: u32) -> &mut Self { self.inner.uid(id); self diff --git a/src/sys.rs b/src/sys.rs index 0d897bc..36d87c1 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -76,6 +76,32 @@ pub fn session_leader( } } +pub fn set_process_group_child( + pg: Option, +) -> impl FnMut() -> std::io::Result<()> { + move || { + nix::unistd::setpgid( + nix::unistd::Pid::from_raw(0), + pg.map_or(nix::unistd::Pid::from_raw(0), |pid| { + nix::unistd::Pid::from_raw(pid.try_into().unwrap()) + }), + )?; + Ok(()) + } +} + +pub fn set_process_group_parent( + pid: u32, + pg: Option, +) -> nix::Result<()> { + nix::unistd::setpgid( + nix::unistd::Pid::from_raw(pid.try_into().unwrap()), + pg.map_or(nix::unistd::Pid::from_raw(0), |pid| { + nix::unistd::Pid::from_raw(pid.try_into().unwrap()) + }), + ) +} + fn set_controlling_terminal(fd: std::os::unix::io::RawFd) -> nix::Result<()> { // Safety: std::fs::File is required to contain a valid file descriptor unsafe { set_controlling_terminal_unsafe(fd, std::ptr::null()) } -- cgit v1.2.3-54-g00ecf