From f664ac9d36c9fe1914745361d890cb40f878defc Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 16 Jul 2020 01:58:01 -0400 Subject: slightly better process exit handling --- src/command.rs | 57 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'src/command.rs') diff --git a/src/command.rs b/src/command.rs index b2d8ef7..481804f 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,41 +1,58 @@ use crate::error::*; use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; +use std::os::unix::process::CommandExt as _; pub struct Command { pty: crate::pty::Pty, command: std::process::Command, + slave_fh: Option, } impl Command { - pub fn new>( - program: S, - ) -> Result { + pub fn new>(program: S) -> Result { let pty = crate::pty::Pty::new()?; - let fd = pty.master().as_raw_fd(); - let stdin = unsafe { std::process::Stdio::from_raw_fd(fd) }; - let stdout = unsafe { std::process::Stdio::from_raw_fd(fd) }; - let stderr = unsafe { std::process::Stdio::from_raw_fd(fd) }; + let master_fd = pty.master().as_raw_fd(); + let slave_fh = pty.slave()?; + let slave_fd = slave_fh.as_raw_fd(); let mut command = std::process::Command::new(program); - command.stdin(stdin).stdout(stdout).stderr(stderr); - Ok(Self { pty, command }) + command + .stdin(unsafe { std::process::Stdio::from_raw_fd(slave_fd) }) + .stdout(unsafe { std::process::Stdio::from_raw_fd(slave_fd) }) + .stderr(unsafe { std::process::Stdio::from_raw_fd(slave_fd) }); + unsafe { + command.pre_exec(move || { + // XXX unwrap + nix::unistd::close(master_fd) + .map_err(|e| e.as_errno().unwrap())?; + nix::unistd::close(slave_fd) + .map_err(|e| e.as_errno().unwrap())?; + Ok(()) + }); + } + Ok(Self { + pty, + command, + slave_fh: Some(slave_fh), + }) } pub fn pty(&self) -> &std::fs::File { - self.pty.slave() + self.pty.master() } -} - -impl std::ops::Deref for Command { - type Target = std::process::Command; - fn deref(&self) -> &Self::Target { - &self.command + pub fn args(&mut self, args: I) -> &mut Self + where + I: IntoIterator, + S: AsRef, + { + self.command.args(args); + self } -} -impl std::ops::DerefMut for Command { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.command + pub fn spawn(&mut self) -> Result { + let child = self.command.spawn()?; + self.slave_fh = None; + Ok(child) } } -- cgit v1.2.3-54-g00ecf