diff --git a/reverie-process/src/fd.rs b/reverie-process/src/fd.rs index f77b106..66d8634 100644 --- a/reverie-process/src/fd.rs +++ b/reverie-process/src/fd.rs @@ -13,6 +13,7 @@ use std::ffi::CStr; use std::io; use std::io::Read; use std::io::Write; +use std::os::fd::OwnedFd; use std::os::unix::io::AsRawFd; use std::os::unix::io::FromRawFd; use std::os::unix::io::IntoRawFd; @@ -232,6 +233,12 @@ impl From for std::fs::File { } } +impl From for Fd { + fn from(fd: OwnedFd) -> Self { + Self(fd.into_raw_fd()) + } +} + impl AsyncFd { pub fn new(fd: Fd) -> Result { fd.set_nonblocking()?; diff --git a/reverie-process/src/stdio.rs b/reverie-process/src/stdio.rs index b7c076b..02fe431 100644 --- a/reverie-process/src/stdio.rs +++ b/reverie-process/src/stdio.rs @@ -10,6 +10,7 @@ use core::pin::Pin; use core::task::Context; use core::task::Poll; use std::io; +use std::os::fd::OwnedFd; use std::os::unix::io::AsRawFd; use std::os::unix::io::FromRawFd; use std::os::unix::io::IntoRawFd; @@ -207,18 +208,36 @@ impl FromRawFd for ChildStdin { } } +impl From for ChildStdin { + fn from(fd: OwnedFd) -> Self { + Self::new(fd.into()).unwrap() + } +} + impl FromRawFd for ChildStdout { unsafe fn from_raw_fd(fd: i32) -> Self { Self::new(Fd::new(fd)).unwrap() } } +impl From for ChildStdout { + fn from(fd: OwnedFd) -> Self { + Self::new(fd.into()).unwrap() + } +} + impl FromRawFd for ChildStderr { unsafe fn from_raw_fd(fd: i32) -> Self { Self::new(Fd::new(fd)).unwrap() } } +impl From for ChildStderr { + fn from(fd: OwnedFd) -> Self { + Self::new(fd.into()).unwrap() + } +} + impl From for ChildStdin { fn from(io: tokio::process::ChildStdin) -> Self { let fd = io.as_raw_fd(); diff --git a/reverie-ptrace/src/tracer.rs b/reverie-ptrace/src/tracer.rs index c9ebf84..c3b4c76 100644 --- a/reverie-ptrace/src/tracer.rs +++ b/reverie-ptrace/src/tracer.rs @@ -10,6 +10,8 @@ use std::io::Write; use std::net::SocketAddr; +use std::os::fd::AsRawFd; +use std::os::fd::OwnedFd; use std::path::PathBuf; use std::sync::Arc; @@ -582,6 +584,11 @@ where let (read1, write1) = unistd::pipe().map_err(from_nix_error)?; let (read2, write2) = unistd::pipe().map_err(from_nix_error)?; + let read1 = unsafe { OwnedFd::from_raw_fd(read1) }; + let write1 = unsafe { OwnedFd::from_raw_fd(write1) }; + let read2 = unsafe { OwnedFd::from_raw_fd(read2) }; + let write2 = unsafe { OwnedFd::from_raw_fd(write2) }; + // Disable io redirection just before forking. We want the child process to // be able to call `println!()` and have that output go to stdout. // @@ -592,15 +599,13 @@ where // panicking, etc). We make a best-effort attempt to solve some of these issues. match unsafe { unistd::fork() }.expect("unistd::fork failed") { ForkResult::Child => { - unistd::close(read1) - .and_then(|_| unistd::close(read2)) - .map_err(from_nix_error)?; + drop(read1); + drop(read2); if capture_output { - unistd::dup2(write1, 1) - .and_then(|_| unistd::dup2(write2, 2)) - .and_then(|_| unistd::close(write1)) - .and_then(|_| unistd::close(write2)) - .map_err(from_nix_error)?; + unistd::dup2(write1.as_raw_fd(), 1).map_err(from_nix_error)?; + unistd::dup2(write2.as_raw_fd(), 2).map_err(from_nix_error)?; + drop(write1); + drop(write2); } init_tracee(events.has_rdtsc()).expect("init_tracee failed"); @@ -627,13 +632,11 @@ where let guest_pid = Pid::from(child); let child = Running::new(guest_pid); - unistd::close(write1) - .and_then(|_| unistd::close(write2)) - .map_err(from_nix_error) - .unwrap(); + drop(write1); + drop(write2); - let stdout = unsafe { ChildStdout::from_raw_fd(read1) }; - let stderr = unsafe { ChildStderr::from_raw_fd(read2) }; + let stdout = read1.into(); + let stderr = read2.into(); let tracer = match postspawn::(child, gref.clone(), config, &events, None).await { Ok(tracer) => tracer, Err(TraceError::Errno(err)) => return Err(Error::Errno(err)),