process: add {ChildStd*}::into_owned_{fd, handle} (#5899)

This commit is contained in:
Jiahao XU
2023-08-09 16:04:53 +02:00
committed by GitHub
parent ee44dc98d8
commit 0a631f88e8
4 changed files with 112 additions and 75 deletions
+3
View File
@@ -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)
+83 -67
View File
@@ -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
@@ -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()
}
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 AsRawFd for $type {
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 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()
}
}
impl AsFd for ChildStdout {
fn as_fd(&self) -> BorrowedFd<'_> {
unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
}
}
impl AsRawFd for ChildStderr {
fn as_raw_fd(&self) -> RawFd {
self.inner.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 AsRawHandle for $type {
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 ChildStdin {
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 $type {
fn as_raw_handle(&self) -> RawHandle {
todo!("For doc generation only")
}
}
impl AsHandle for $type {
fn as_handle(&self) -> BorrowedHandle<'_> {
todo!("For doc generation only")
}
}
};
}
impl AsRawHandle for ChildStdout {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
}
impl AsHandle for ChildStdout {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}
impl AsRawHandle for ChildStderr {
fn as_raw_handle(&self) -> RawHandle {
self.inner.as_raw_handle()
}
}
impl AsHandle for ChildStderr {
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}
impl_traits!(ChildStdin);
impl_traits!(ChildStdout);
impl_traits!(ChildStderr);
}
#[cfg(all(test, not(loom)))]
+13 -3
View File
@@ -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;
@@ -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
@@ -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 {
@@ -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)
+13 -5
View File
@@ -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};
@@ -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()
@@ -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> {