Skip to content

Commit

Permalink
process: add {ChildStd*}::into_owned_{fd, handle} (#5899)
Browse files Browse the repository at this point in the history
  • Loading branch information
NobodyXu committed Aug 9, 2023
1 parent ee44dc9 commit 0a631f8
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 70 deletions.
3 changes: 3 additions & 0 deletions tokio/src/doc/os.rs
Expand Up @@ -11,6 +11,9 @@ pub mod windows {
/// See [std::os::windows::io::RawHandle](https://doc.rust-lang.org/std/os/windows/io/type.RawHandle.html)
pub type RawHandle = crate::doc::NotDefinedHere;

/// See [std::os::windows::io::OwnedHandle](https://doc.rust-lang.org/std/os/windows/io/struct.OwnedHandle.html)
pub type OwnedHandle = crate::doc::NotDefinedHere;

/// See [std::os::windows::io::AsRawHandle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html)
pub trait AsRawHandle {
/// See [std::os::windows::io::AsRawHandle::as_raw_handle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html#tymethod.as_raw_handle)
Expand Down
140 changes: 78 additions & 62 deletions tokio/src/process/mod.rs
Expand Up @@ -259,7 +259,7 @@ use std::os::unix::process::CommandExt;
use std::os::windows::process::CommandExt;

cfg_windows! {
use crate::os::windows::io::{AsRawHandle, RawHandle, AsHandle, BorrowedHandle};
use crate::os::windows::io::{AsRawHandle, RawHandle};
}

/// This structure mimics the API of [`std::process::Command`] found in the standard library, but
Expand Down Expand Up @@ -1447,84 +1447,100 @@ impl TryInto<Stdio> for ChildStderr {
}

#[cfg(unix)]
#[cfg_attr(docsrs, doc(cfg(unix)))]
mod sys {
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
use std::{
io,
os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
};

use super::{ChildStderr, ChildStdin, ChildStdout};

impl AsRawFd for ChildStdin {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

impl AsFd for ChildStdin {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}

impl AsRawFd for ChildStdout {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
macro_rules! impl_traits {
($type:ty) => {
impl $type {
/// Convert into [`OwnedFd`].
pub fn into_owned_fd(self) -> io::Result<OwnedFd> {
self.inner.into_owned_fd()
}
}

impl AsFd for ChildStdout {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
impl AsRawFd for $type {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

impl AsRawFd for ChildStderr {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
impl AsFd for $type {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
};
}

impl AsFd for ChildStderr {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
impl_traits!(ChildStdin);
impl_traits!(ChildStdout);
impl_traits!(ChildStderr);
}

cfg_windows! {
impl AsRawHandle for ChildStdin {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
}
#[cfg(any(windows, docsrs))]
#[cfg_attr(docsrs, doc(cfg(windows)))]
mod windows {
use super::*;
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, OwnedHandle, RawHandle};

#[cfg(not(docsrs))]
macro_rules! impl_traits {
($type:ty) => {
impl $type {
/// Convert into [`OwnedHandle`].
pub fn into_owned_handle(self) -> io::Result<OwnedHandle> {
self.inner.into_owned_handle()
}
}

impl AsHandle for ChildStdin {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}
impl AsRawHandle for $type {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
}

impl AsRawHandle for ChildStdout {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
impl AsHandle for $type {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}
};
}

impl AsHandle for ChildStdout {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}
#[cfg(docsrs)]
macro_rules! impl_traits {
($type:ty) => {
impl $type {
/// Convert into [`OwnedHandle`].
pub fn into_owned_handle(self) -> io::Result<OwnedHandle> {
todo!("For doc generation only")
}
}

impl AsRawHandle for ChildStderr {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
}
impl AsRawHandle for $type {
fn as_raw_handle(&self) -> RawHandle {
todo!("For doc generation only")
}
}

impl AsHandle for ChildStderr {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
impl AsHandle for $type {
fn as_handle(&self) -> BorrowedHandle<'_> {
todo!("For doc generation only")
}
}
};
}

impl_traits!(ChildStdin);
impl_traits!(ChildStdout);
impl_traits!(ChildStderr);
}

#[cfg(all(test, not(loom)))]
Expand Down
16 changes: 13 additions & 3 deletions tokio/src/process/unix/mod.rs
Expand Up @@ -39,7 +39,7 @@ use std::fmt;
use std::fs::File;
use std::future::Future;
use std::io;
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use std::pin::Pin;
use std::process::{Child as StdChild, ExitStatus, Stdio};
use std::task::Context;
Expand Down Expand Up @@ -200,7 +200,7 @@ impl AsFd for Pipe {
}
}

pub(crate) fn convert_to_stdio(io: ChildStdio) -> io::Result<Stdio> {
fn convert_to_blocking_file(io: ChildStdio) -> io::Result<File> {
let mut fd = io.inner.into_inner()?.fd;

// Ensure that the fd to be inherited is set to *blocking* mode, as this
Expand All @@ -209,7 +209,11 @@ pub(crate) fn convert_to_stdio(io: ChildStdio) -> io::Result<Stdio> {
// change it to nonblocking mode.
set_nonblocking(&mut fd, false)?;

Ok(Stdio::from(fd))
Ok(fd)
}

pub(crate) fn convert_to_stdio(io: ChildStdio) -> io::Result<Stdio> {
convert_to_blocking_file(io).map(Stdio::from)
}

impl Source for Pipe {
Expand Down Expand Up @@ -240,6 +244,12 @@ pub(crate) struct ChildStdio {
inner: PollEvented<Pipe>,
}

impl ChildStdio {
pub(super) fn into_owned_fd(self) -> io::Result<OwnedFd> {
convert_to_blocking_file(self).map(OwnedFd::from)
}
}

impl fmt::Debug for ChildStdio {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(fmt)
Expand Down
18 changes: 13 additions & 5 deletions tokio/src/process/windows.rs
Expand Up @@ -24,7 +24,7 @@ use std::fmt;
use std::fs::File as StdFile;
use std::future::Future;
use std::io;
use std::os::windows::prelude::{AsRawHandle, IntoRawHandle, RawHandle};
use std::os::windows::prelude::{AsRawHandle, IntoRawHandle, OwnedHandle, RawHandle};
use std::pin::Pin;
use std::process::Stdio;
use std::process::{Child as StdChild, Command as StdCommand, ExitStatus};
Expand Down Expand Up @@ -195,6 +195,12 @@ pub(crate) struct ChildStdio {
io: Blocking<ArcFile>,
}

impl ChildStdio {
pub(super) fn into_owned_handle(self) -> io::Result<OwnedHandle> {
convert_to_file(self).map(OwnedHandle::from)
}
}

impl AsRawHandle for ChildStdio {
fn as_raw_handle(&self) -> RawHandle {
self.raw.as_raw_handle()
Expand Down Expand Up @@ -240,13 +246,15 @@ where
Ok(ChildStdio { raw, io })
}

pub(crate) fn convert_to_stdio(child_stdio: ChildStdio) -> io::Result<Stdio> {
fn convert_to_file(child_stdio: ChildStdio) -> io::Result<StdFile> {
let ChildStdio { raw, io } = child_stdio;
drop(io); // Try to drop the Arc count here

Arc::try_unwrap(raw)
.or_else(|raw| duplicate_handle(&*raw))
.map(Stdio::from)
Arc::try_unwrap(raw).or_else(|raw| duplicate_handle(&*raw))
}

pub(crate) fn convert_to_stdio(child_stdio: ChildStdio) -> io::Result<Stdio> {
convert_to_file(child_stdio).map(Stdio::from)
}

fn duplicate_handle<T: AsRawHandle>(io: &T) -> io::Result<StdFile> {
Expand Down

0 comments on commit 0a631f8

Please sign in to comment.