From 04b141ae3409c111c65466252e0987e65aab3363 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 30 Dec 2021 22:20:13 -0500 Subject: properly handle configuration when calling spawn multiple times --- src/blocking/command.rs | 48 ++++++++++++++++++++++++++++++------------------ src/command.rs | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 58 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/blocking/command.rs b/src/blocking/command.rs index ed36443..0fa97ea 100644 --- a/src/blocking/command.rs +++ b/src/blocking/command.rs @@ -2,9 +2,10 @@ use std::os::unix::process::CommandExt as _; pub struct Command { inner: std::process::Command, - stdin: Option, - stdout: Option, - stderr: Option, + stdin: bool, + stdout: bool, + stderr: bool, + pre_exec_set: bool, pre_exec: Option< Box std::io::Result<()> + Send + Sync + 'static>, >, @@ -14,9 +15,10 @@ impl Command { pub fn new>(program: S) -> Self { Self { inner: std::process::Command::new(program), - stdin: None, - stdout: None, - stderr: None, + stdin: false, + stdout: false, + stderr: false, + pre_exec_set: false, pre_exec: None, } } @@ -77,25 +79,28 @@ impl Command { pub fn stdin>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stdin = cfg.map(Into::into); + self.stdin = true; + self.inner.stdin(cfg); self } pub fn stdout>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stdout = cfg.map(Into::into); + self.stdout = true; + self.inner.stdout(cfg); self } pub fn stderr>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stderr = cfg.map(Into::into); + self.stderr = true; + self.inner.stderr(cfg); self } @@ -106,13 +111,19 @@ impl Command { let pts = pty.pts(); let (stdin, stdout, stderr) = crate::sys::setup_subprocess(pts)?; - self.inner.stdin(self.stdin.take().unwrap_or(stdin)); - self.inner.stdout(self.stdout.take().unwrap_or(stdout)); - self.inner.stderr(self.stderr.take().unwrap_or(stderr)); + if !self.stdin { + self.inner.stdin(stdin); + } + if !self.stdout { + self.inner.stdout(stdout); + } + if !self.stderr { + self.inner.stderr(stderr); + } let mut session_leader = crate::sys::session_leader(pts); - // safe because setsid() is an async-signal-safe function and ioctl() - // is a raw syscall (which is inherently async-signal-safe). + // Safety: setsid() 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 || { @@ -121,9 +132,10 @@ impl Command { Ok(()) }) }; - } else { + } else if !self.pre_exec_set { unsafe { self.inner.pre_exec(session_leader) }; } + self.pre_exec_set = true; Ok(self.inner.spawn()?) } diff --git a/src/command.rs b/src/command.rs index cd1c8a3..00b51e7 100644 --- a/src/command.rs +++ b/src/command.rs @@ -2,9 +2,10 @@ use async_process::unix::CommandExt as _; pub struct Command { inner: async_process::Command, - stdin: Option, - stdout: Option, - stderr: Option, + stdin: bool, + stdout: bool, + stderr: bool, + pre_exec_set: bool, pre_exec: Option< Box std::io::Result<()> + Send + Sync + 'static>, >, @@ -14,9 +15,10 @@ impl Command { pub fn new>(program: S) -> Self { Self { inner: async_process::Command::new(program), - stdin: None, - stdout: None, - stderr: None, + stdin: false, + stdout: false, + stderr: false, + pre_exec_set: false, pre_exec: None, } } @@ -77,25 +79,28 @@ impl Command { pub fn stdin>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stdin = cfg.map(Into::into); + self.stdin = true; + self.inner.stdin(cfg); self } pub fn stdout>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stdout = cfg.map(Into::into); + self.stdout = true; + self.inner.stdout(cfg); self } pub fn stderr>( &mut self, - cfg: Option, + cfg: T, ) -> &mut Self { - self.stderr = cfg.map(Into::into); + self.stderr = true; + self.inner.stderr(cfg); self } @@ -106,9 +111,15 @@ impl Command { let pts = pty.pts(); let (stdin, stdout, stderr) = crate::sys::setup_subprocess(pts)?; - self.inner.stdin(self.stdin.take().unwrap_or(stdin)); - self.inner.stdout(self.stdout.take().unwrap_or(stdout)); - self.inner.stderr(self.stderr.take().unwrap_or(stderr)); + if !self.stdin { + self.inner.stdin(stdin); + } + if !self.stdout { + self.inner.stdout(stdout); + } + if !self.stderr { + self.inner.stderr(stderr); + } let mut session_leader = crate::sys::session_leader(pts); // Safety: setsid() is an async-signal-safe function and ioctl() is a @@ -121,9 +132,10 @@ impl Command { Ok(()) }) }; - } else { + } else if !self.pre_exec_set { unsafe { self.inner.pre_exec(session_leader) }; } + self.pre_exec_set = true; Ok(self.inner.spawn()?) } -- cgit v1.2.3-54-g00ecf