Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process: Impl {ChildStd*}::into_owned_{fd, handle} #5899

Merged
merged 3 commits into from Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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