std: reorganize pipe implementations

This commit is contained in:
joboet 2025-09-19 20:56:07 +02:00
parent 3391c01336
commit 860716faa3
No known key found for this signature in database
GPG key ID: 704E0149B0194B3C
39 changed files with 296 additions and 517 deletions

View file

@ -1,5 +1,5 @@
use crate::io;
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
use crate::sys::pipe as imp;
use crate::sys_common::{FromInner, IntoInner};
/// Creates an anonymous pipe.
@ -84,39 +84,39 @@ use crate::sys_common::{FromInner, IntoInner};
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[inline]
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
imp::pipe().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
}
/// Read end of an anonymous pipe.
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[derive(Debug)]
pub struct PipeReader(pub(crate) AnonPipe);
pub struct PipeReader(pub(crate) imp::Pipe);
/// Write end of an anonymous pipe.
#[stable(feature = "anonymous_pipe", since = "1.87.0")]
#[derive(Debug)]
pub struct PipeWriter(pub(crate) AnonPipe);
pub struct PipeWriter(pub(crate) imp::Pipe);
impl FromInner<AnonPipe> for PipeReader {
fn from_inner(inner: AnonPipe) -> Self {
impl FromInner<imp::Pipe> for PipeReader {
fn from_inner(inner: imp::Pipe) -> Self {
Self(inner)
}
}
impl IntoInner<AnonPipe> for PipeReader {
fn into_inner(self) -> AnonPipe {
impl IntoInner<imp::Pipe> for PipeReader {
fn into_inner(self) -> imp::Pipe {
self.0
}
}
impl FromInner<AnonPipe> for PipeWriter {
fn from_inner(inner: AnonPipe) -> Self {
impl FromInner<imp::Pipe> for PipeWriter {
fn from_inner(inner: imp::Pipe) -> Self {
Self(inner)
}
}
impl IntoInner<AnonPipe> for PipeWriter {
fn into_inner(self) -> AnonPipe {
impl IntoInner<imp::Pipe> for PipeWriter {
fn into_inner(self) -> imp::Pipe {
self.0
}
}

View file

@ -8,6 +8,7 @@ use crate::ffi::OsStr;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::path::Path;
use crate::sealed::Sealed;
use crate::sys::process::ChildPipe;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::{io, process, sys};
@ -511,7 +512,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
/// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file descriptor.
#[inline]
fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
child_stdin.into_inner().into_inner().into_inner()
child_stdin.into_inner().into_inner()
}
}
@ -523,8 +524,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
impl From<OwnedFd> for process::ChildStdin {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStdin {
let fd = sys::fd::FileDesc::from_inner(fd);
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = ChildPipe::from_inner(fd);
process::ChildStdin::from_inner(pipe)
}
}
@ -542,7 +542,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
/// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file descriptor.
#[inline]
fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
child_stdout.into_inner().into_inner().into_inner()
child_stdout.into_inner().into_inner()
}
}
@ -554,8 +554,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
impl From<OwnedFd> for process::ChildStdout {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStdout {
let fd = sys::fd::FileDesc::from_inner(fd);
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = ChildPipe::from_inner(fd);
process::ChildStdout::from_inner(pipe)
}
}
@ -573,7 +572,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
/// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file descriptor.
#[inline]
fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
child_stderr.into_inner().into_inner().into_inner()
child_stderr.into_inner().into_inner()
}
}
@ -585,8 +584,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
impl From<OwnedFd> for process::ChildStderr {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStderr {
let fd = sys::fd::FileDesc::from_inner(fd);
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = ChildPipe::from_inner(fd);
process::ChildStderr::from_inner(pipe)
}
}

View file

@ -117,7 +117,7 @@ impl IntoRawHandle for process::ChildStderr {
impl From<OwnedHandle> for process::ChildStdin {
fn from(handle: OwnedHandle) -> process::ChildStdin {
let handle = sys::handle::Handle::from_inner(handle);
let pipe = sys::pipe::AnonPipe::from_inner(handle);
let pipe = sys::process::ChildPipe::from_inner(handle);
process::ChildStdin::from_inner(pipe)
}
}
@ -130,7 +130,7 @@ impl From<OwnedHandle> for process::ChildStdin {
impl From<OwnedHandle> for process::ChildStdout {
fn from(handle: OwnedHandle) -> process::ChildStdout {
let handle = sys::handle::Handle::from_inner(handle);
let pipe = sys::pipe::AnonPipe::from_inner(handle);
let pipe = sys::process::ChildPipe::from_inner(handle);
process::ChildStdout::from_inner(pipe)
}
}
@ -143,7 +143,7 @@ impl From<OwnedHandle> for process::ChildStdout {
impl From<OwnedHandle> for process::ChildStderr {
fn from(handle: OwnedHandle) -> process::ChildStderr {
let handle = sys::handle::Handle::from_inner(handle);
let pipe = sys::pipe::AnonPipe::from_inner(handle);
let pipe = sys::process::ChildPipe::from_inner(handle);
process::ChildStderr::from_inner(pipe)
}
}

View file

@ -166,7 +166,6 @@ use crate::io::prelude::*;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::num::NonZero;
use crate::path::Path;
use crate::sys::pipe::{AnonPipe, read2};
use crate::sys::process as imp;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::{fmt, fs, str};
@ -300,9 +299,9 @@ impl fmt::Debug for Child {
///
/// Used to pass pipe handles between this module and [`imp`].
pub(crate) struct StdioPipes {
pub stdin: Option<AnonPipe>,
pub stdout: Option<AnonPipe>,
pub stderr: Option<AnonPipe>,
pub stdin: Option<imp::ChildPipe>,
pub stdout: Option<imp::ChildPipe>,
pub stderr: Option<imp::ChildPipe>,
}
/// A handle to a child process's standard input (stdin).
@ -317,7 +316,7 @@ pub(crate) struct StdioPipes {
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin {
inner: AnonPipe,
inner: imp::ChildPipe,
}
// In addition to the `impl`s here, `ChildStdin` also has `impl`s for
@ -366,21 +365,21 @@ impl Write for &ChildStdin {
}
}
impl AsInner<AnonPipe> for ChildStdin {
impl AsInner<imp::ChildPipe> for ChildStdin {
#[inline]
fn as_inner(&self) -> &AnonPipe {
fn as_inner(&self) -> &imp::ChildPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStdin {
fn into_inner(self) -> AnonPipe {
impl IntoInner<imp::ChildPipe> for ChildStdin {
fn into_inner(self) -> imp::ChildPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStdin {
fn from_inner(pipe: AnonPipe) -> ChildStdin {
impl FromInner<imp::ChildPipe> for ChildStdin {
fn from_inner(pipe: imp::ChildPipe) -> ChildStdin {
ChildStdin { inner: pipe }
}
}
@ -403,7 +402,7 @@ impl fmt::Debug for ChildStdin {
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout {
inner: AnonPipe,
inner: imp::ChildPipe,
}
// In addition to the `impl`s here, `ChildStdout` also has `impl`s for
@ -436,21 +435,21 @@ impl Read for ChildStdout {
}
}
impl AsInner<AnonPipe> for ChildStdout {
impl AsInner<imp::ChildPipe> for ChildStdout {
#[inline]
fn as_inner(&self) -> &AnonPipe {
fn as_inner(&self) -> &imp::ChildPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStdout {
fn into_inner(self) -> AnonPipe {
impl IntoInner<imp::ChildPipe> for ChildStdout {
fn into_inner(self) -> imp::ChildPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStdout {
fn from_inner(pipe: AnonPipe) -> ChildStdout {
impl FromInner<imp::ChildPipe> for ChildStdout {
fn from_inner(pipe: imp::ChildPipe) -> ChildStdout {
ChildStdout { inner: pipe }
}
}
@ -473,7 +472,7 @@ impl fmt::Debug for ChildStdout {
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr {
inner: AnonPipe,
inner: imp::ChildPipe,
}
// In addition to the `impl`s here, `ChildStderr` also has `impl`s for
@ -506,21 +505,21 @@ impl Read for ChildStderr {
}
}
impl AsInner<AnonPipe> for ChildStderr {
impl AsInner<imp::ChildPipe> for ChildStderr {
#[inline]
fn as_inner(&self) -> &AnonPipe {
fn as_inner(&self) -> &imp::ChildPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStderr {
fn into_inner(self) -> AnonPipe {
impl IntoInner<imp::ChildPipe> for ChildStderr {
fn into_inner(self) -> imp::ChildPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStderr {
fn from_inner(pipe: AnonPipe) -> ChildStderr {
impl FromInner<imp::ChildPipe> for ChildStderr {
fn from_inner(pipe: imp::ChildPipe) -> ChildStderr {
ChildStderr { inner: pipe }
}
}
@ -2380,7 +2379,7 @@ impl Child {
res.unwrap();
}
(Some(out), Some(err)) => {
let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
let res = imp::read_output(out.inner, &mut stdout, err.inner, &mut stderr);
res.unwrap();
}
}

View file

@ -1,11 +0,0 @@
use crate::io;
use crate::sys::fd::FileDesc;
use crate::sys::pipe::anon_pipe;
use crate::sys_common::IntoInner;
pub type AnonPipe = FileDesc;
#[inline]
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
}

View file

@ -1,11 +0,0 @@
use crate::io;
use crate::sys::fd::FileDesc;
use crate::sys::pipe::anon_pipe;
use crate::sys_common::IntoInner;
pub type AnonPipe = FileDesc;
#[inline]
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
}

View file

@ -1,7 +0,0 @@
use crate::io;
pub use crate::sys::pipe::AnonPipe;
#[inline]
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
Err(io::Error::UNSUPPORTED_PLATFORM)
}

View file

@ -13,7 +13,6 @@ mod pal;
mod alloc;
mod personality;
pub mod anonymous_pipe;
pub mod args;
pub mod backtrace;
pub mod cmath;
@ -26,6 +25,7 @@ pub mod io;
pub mod net;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod platform_version;
pub mod process;
pub mod random;

View file

@ -23,8 +23,6 @@ use crate::sys::env;
pub mod futex;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub mod time;
pub fn unsupported<T>() -> crate::io::Result<T> {

View file

@ -1,7 +1,6 @@
#![allow(unsafe_op_in_unsafe_fn)]
pub mod os;
pub mod pipe;
pub mod time;
pub use moto_rt::futex;

View file

@ -1,121 +0,0 @@
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys::fd::FileDesc;
use crate::sys::map_motor_error;
use crate::sys_common::{FromInner, IntoInner};
#[derive(Debug)]
pub struct AnonPipe(FileDesc);
impl From<moto_rt::RtFd> for AnonPipe {
fn from(rt_fd: moto_rt::RtFd) -> AnonPipe {
unsafe { AnonPipe::from_raw_fd(rt_fd) }
}
}
impl AnonPipe {
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
moto_rt::fs::read(self.as_raw_fd(), buf).map_err(map_motor_error)
}
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
crate::io::default_read_buf(|buf| self.read(buf), cursor)
}
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
crate::io::default_read_vectored(|b| self.read(b), bufs)
}
pub fn is_read_vectored(&self) -> bool {
false
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
moto_rt::fs::write(self.as_raw_fd(), buf).map_err(map_motor_error)
}
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
crate::io::default_write_vectored(|b| self.write(b), bufs)
}
pub fn is_write_vectored(&self) -> bool {
false
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut temp_vec = Vec::new();
let mut size = 0_usize;
loop {
temp_vec.resize(256, 0_u8);
match self.read(&mut temp_vec[..]) {
Ok(sz) => {
if sz == 0 {
return Ok(size);
}
size += sz;
temp_vec.truncate(sz);
buf.append(&mut temp_vec);
}
Err(err) => {
if size != 0 {
return Ok(size);
} else {
return Err(err);
}
}
}
}
}
}
impl AsRawFd for AnonPipe {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl FromRawFd for AnonPipe {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
let desc = FileDesc::from_raw_fd(fd);
Self(desc)
}
}
impl IntoRawFd for AnonPipe {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
impl AsFd for AnonPipe {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl IntoInner<OwnedFd> for AnonPipe {
fn into_inner(self) -> OwnedFd {
self.0.into_inner()
}
}
impl IntoInner<FileDesc> for AnonPipe {
fn into_inner(self) -> FileDesc {
self.0
}
}
impl FromInner<OwnedFd> for AnonPipe {
fn from_inner(owned_fd: OwnedFd) -> Self {
Self(FileDesc::from_inner(owned_fd))
}
}
pub fn read2(_p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
Err(io::Error::from_raw_os_error(moto_rt::E_NOT_IMPLEMENTED.into()))
}
#[inline]
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
Err(io::Error::UNSUPPORTED_PLATFORM)
}

View file

@ -11,8 +11,6 @@ use crate::sync::atomic::{Atomic, AtomicBool, Ordering};
pub mod abi;
mod libunwind_integration;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub mod thread_parking;
pub mod time;
pub mod waitqueue;

View file

@ -18,8 +18,6 @@ pub mod itron {
// `crate::sys::error`
pub(crate) mod error;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub use self::itron::thread_parking;
pub mod time;

View file

@ -7,8 +7,6 @@
#![allow(dead_code)]
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[allow(non_upper_case_globals)]
#[path = "../unix/time.rs"]
pub mod time;

View file

@ -5,8 +5,6 @@
mod common;
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/time.rs"]
pub mod time;

View file

@ -15,8 +15,6 @@
pub mod helpers;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub mod time;
#[cfg(test)]

View file

@ -8,7 +8,6 @@ pub mod futex;
#[cfg(target_os = "linux")]
pub mod linux;
pub mod os;
pub mod pipe;
pub mod stack_overflow;
pub mod sync;
pub mod thread_parking;

View file

@ -1,184 +0,0 @@
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::mem;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
use crate::sys::{cvt, cvt_r};
use crate::sys_common::{FromInner, IntoInner};
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
////////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
pub struct AnonPipe(FileDesc);
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
let mut fds = [0; 2];
// The only known way right now to create atomically set the CLOEXEC flag is
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
// and musl 0.9.3, and some other targets also have it.
cfg_select! {
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "hurd",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "redox"
) => {
unsafe {
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
Ok((AnonPipe(FileDesc::from_raw_fd(fds[0])), AnonPipe(FileDesc::from_raw_fd(fds[1]))))
}
}
_ => {
unsafe {
cvt(libc::pipe(fds.as_mut_ptr()))?;
let fd0 = FileDesc::from_raw_fd(fds[0]);
let fd1 = FileDesc::from_raw_fd(fds[1]);
fd0.set_cloexec()?;
fd1.set_cloexec()?;
Ok((AnonPipe(fd0), AnonPipe(fd1)))
}
}
}
}
impl AnonPipe {
#[allow(dead_code)]
// FIXME: This function seems legitimately unused.
pub fn try_clone(&self) -> io::Result<Self> {
self.0.duplicate().map(Self)
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
self.0.read_buf(buf)
}
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0.read_vectored(bufs)
}
#[inline]
pub fn is_read_vectored(&self) -> bool {
self.0.is_read_vectored()
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0.write_vectored(bufs)
}
#[inline]
pub fn is_write_vectored(&self) -> bool {
self.0.is_write_vectored()
}
#[allow(dead_code)]
// FIXME: This function seems legitimately unused.
pub fn as_file_desc(&self) -> &FileDesc {
&self.0
}
}
impl IntoInner<FileDesc> for AnonPipe {
fn into_inner(self) -> FileDesc {
self.0
}
}
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
// Set both pipes into nonblocking mode as we're gonna be reading from both
// in the `select` loop below, and we wouldn't want one to block the other!
let p1 = p1.into_inner();
let p2 = p2.into_inner();
p1.set_nonblocking(true)?;
p2.set_nonblocking(true)?;
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
fds[0].fd = p1.as_raw_fd();
fds[0].events = libc::POLLIN;
fds[1].fd = p2.as_raw_fd();
fds[1].events = libc::POLLIN;
loop {
// wait for either pipe to become readable using `poll`
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
if fds[0].revents != 0 && read(&p1, v1)? {
p2.set_nonblocking(false)?;
return p2.read_to_end(v2).map(drop);
}
if fds[1].revents != 0 && read(&p2, v2)? {
p1.set_nonblocking(false)?;
return p1.read_to_end(v1).map(drop);
}
}
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
// EAGAIN. If we hit EOF, then this will happen because the underlying
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
// this case we flip the other fd back into blocking mode and read
// whatever's leftover on that file descriptor.
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
match fd.read_to_end(dst) {
Ok(_) => Ok(true),
Err(e) => {
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|| e.raw_os_error() == Some(libc::EAGAIN)
{
Ok(false)
} else {
Err(e)
}
}
}
}
}
impl AsRawFd for AnonPipe {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
impl AsFd for AnonPipe {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
impl IntoRawFd for AnonPipe {
fn into_raw_fd(self) -> RawFd {
self.0.into_raw_fd()
}
}
impl FromRawFd for AnonPipe {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
Self(FromRawFd::from_raw_fd(raw_fd))
}
}
impl FromInner<FileDesc> for AnonPipe {
fn from_inner(fd: FileDesc) -> Self {
Self(fd)
}
}

View file

@ -1,7 +1,6 @@
#![deny(unsafe_op_in_unsafe_fn)]
pub mod os;
pub mod pipe;
pub mod time;
mod common;

View file

@ -9,8 +9,6 @@
pub mod futex;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub mod stack_overflow;
#[path = "../unix/time.rs"]
pub mod time;

View file

@ -18,8 +18,6 @@
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/time.rs"]
pub mod time;

View file

@ -19,7 +19,6 @@ pub mod c;
pub mod futex;
pub mod handle;
pub mod os;
pub mod pipe;
pub mod time;
cfg_select! {
// We don't care about printing nice error messages for panic=immediate-abort

View file

@ -3,8 +3,6 @@
use crate::os::xous::ffi::exit;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
pub mod time;
#[path = "../unsupported/common.rs"]

View file

@ -12,8 +12,6 @@ pub const WORD_SIZE: usize = size_of::<u32>();
pub mod abi;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/time.rs"]
pub mod time;

View file

@ -3,18 +3,18 @@
cfg_select! {
unix => {
mod unix;
pub use unix::{AnonPipe, pipe};
pub use unix::{Pipe, pipe};
}
windows => {
mod windows;
pub use windows::{AnonPipe, pipe};
pub use windows::{Pipe, pipe};
}
target_os = "motor" => {
mod motor;
pub use motor::{AnonPipe, pipe};
pub use motor::{Pipe, pipe};
}
_ => {
mod unsupported;
pub use unsupported::{AnonPipe, pipe};
pub use unsupported::{Pipe, pipe};
}
}

View file

@ -0,0 +1,9 @@
use crate::io;
use crate::sys::fd::FileDesc;
pub type Pipe = FileDesc;
#[inline]
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
Err(io::Error::UNSUPPORTED_PLATFORM)
}

View file

@ -0,0 +1,44 @@
use crate::io;
use crate::os::fd::FromRawFd;
use crate::sys::fd::FileDesc;
use crate::sys::pal::cvt;
pub type Pipe = FileDesc;
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
let mut fds = [0; 2];
// The only known way right now to create atomically set the CLOEXEC flag is
// to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
// and musl 0.9.3, and some other targets also have it.
cfg_select! {
any(
target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "hurd",
target_os = "illumos",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "redox"
) => {
unsafe {
cvt(libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC))?;
Ok((Pipe::from_raw_fd(fds[0]), Pipe::from_raw_fd(fds[1])))
}
}
_ => {
unsafe {
cvt(libc::pipe(fds.as_mut_ptr()))?;
let fd0 = Pipe::from_raw_fd(fds[0]);
let fd1 = Pipe::from_raw_fd(fds[1]);
fd0.set_cloexec()?;
fd1.set_cloexec()?;
Ok((fd0, fd1))
}
}
}
}

View file

@ -1,16 +1,14 @@
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::sys_common::{FromInner, IntoInner};
pub struct AnonPipe(!);
pub struct Pipe(!);
impl fmt::Debug for AnonPipe {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
#[inline]
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
Err(io::Error::UNSUPPORTED_PLATFORM)
}
impl AnonPipe {
impl Pipe {
pub fn try_clone(&self) -> io::Result<Self> {
self.0
}
@ -52,56 +50,52 @@ impl AnonPipe {
}
}
pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
match p1.0 {}
}
impl FromInner<!> for AnonPipe {
fn from_inner(inner: !) -> Self {
inner
}
}
impl IntoInner<!> for AnonPipe {
fn into_inner(self) -> ! {
impl fmt::Debug for Pipe {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
mod unix_traits {
use super::AnonPipe;
use super::Pipe;
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys_common::FromInner;
use crate::sys_common::{FromInner, IntoInner};
impl AsRawFd for AnonPipe {
impl AsRawFd for Pipe {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.0
}
}
impl AsFd for AnonPipe {
impl AsFd for Pipe {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0
}
}
impl IntoRawFd for AnonPipe {
impl IntoRawFd for Pipe {
fn into_raw_fd(self) -> RawFd {
self.0
}
}
impl FromRawFd for AnonPipe {
impl FromRawFd for Pipe {
unsafe fn from_raw_fd(_: RawFd) -> Self {
panic!("creating pipe on this platform is unsupported!")
}
}
impl FromInner<OwnedFd> for AnonPipe {
impl FromInner<OwnedFd> for Pipe {
fn from_inner(_: OwnedFd) -> Self {
panic!("creating pipe on this platform is unsupported!")
}
}
impl IntoInner<OwnedFd> for Pipe {
fn into_inner(self) -> OwnedFd {
self.0
}
}
}

View file

@ -3,9 +3,9 @@ use crate::sys::c;
use crate::sys::handle::Handle;
use crate::{io, ptr};
pub type AnonPipe = Handle;
pub type Pipe = Handle;
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
pub fn pipe() -> io::Result<(Pipe, Pipe)> {
let mut read_pipe = c::INVALID_HANDLE_VALUE;
let mut write_pipe = c::INVALID_HANDLE_VALUE;

View file

@ -28,7 +28,8 @@ mod env;
pub use env::CommandEnvs;
pub use imp::{
Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
ChildPipe, Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
read_output,
};
#[cfg(any(
@ -45,8 +46,6 @@ pub use imp::{
target_os = "motor"
))]
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
use crate::sys::pipe::read2;
let (mut process, mut pipes) = cmd.spawn(Stdio::MakePipe, false)?;
drop(pipes.stdin.take());
@ -62,7 +61,7 @@ pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<
res.unwrap();
}
(Some(out), Some(err)) => {
let res = read2(out, &mut stdout, err, &mut stderr);
let res = read_output(out, &mut stdout, err, &mut stderr);
res.unwrap();
}
}

View file

@ -9,7 +9,6 @@ use crate::path::Path;
use crate::process::StdioPipes;
use crate::sys::fs::File;
use crate::sys::map_motor_error;
use crate::sys::pipe::AnonPipe;
use crate::sys_common::{AsInner, FromInner};
use crate::{fmt, io};
@ -150,20 +149,26 @@ impl Command {
Ok((
Process { handle },
StdioPipes {
stdin: if stdin >= 0 { Some(stdin.into()) } else { None },
stdout: if stdout >= 0 { Some(stdout.into()) } else { None },
stderr: if stderr >= 0 { Some(stderr.into()) } else { None },
stdin: if stdin >= 0 {
Some(unsafe { ChildPipe::from_raw_fd(stdin) })
} else {
None
},
stdout: if stdout >= 0 {
Some(unsafe { ChildPipe::from_raw_fd(stdout) })
} else {
None
},
stderr: if stderr >= 0 {
Some(unsafe { ChildPipe::from_raw_fd(stderr) })
} else {
None
},
},
))
}
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
unsafe { Stdio::Fd(crate::sys::fd::FileDesc::from_raw_fd(pipe.into_raw_fd())) }
}
}
impl From<crate::sys::fd::FileDesc> for Stdio {
fn from(fd: crate::sys::fd::FileDesc) -> Stdio {
Stdio::Fd(fd)
@ -315,3 +320,14 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
f.debug_list().entries(self.iter.clone()).finish()
}
}
pub type ChildPipe = crate::sys::pipe::Pipe;
pub fn read_output(
_out: ChildPipe,
_stdout: &mut Vec<u8>,
_err: ChildPipe,
_stderr: &mut Vec<u8>,
) -> io::Result<()> {
Err(io::Error::from_raw_os_error(moto_rt::E_NOT_IMPLEMENTED.into()))
}

View file

@ -10,7 +10,6 @@ use crate::process::StdioPipes;
use crate::sys::fs::File;
use crate::sys::pal::helpers;
use crate::sys::pal::os::error_string;
use crate::sys::pipe::AnonPipe;
use crate::sys::unsupported;
use crate::{fmt, io};
@ -204,8 +203,8 @@ pub fn output(command: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>
Ok((ExitStatus(stat), stdout, stderr))
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
impl From<ChildPipe> for Stdio {
fn from(pipe: ChildPipe) -> Stdio {
pipe.diverge()
}
}
@ -356,6 +355,17 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
}
}
pub type ChildPipe = crate::sys::pipe::Pipe;
pub fn read_output(
out: ChildPipe,
_stdout: &mut Vec<u8>,
_err: ChildPipe,
_stderr: &mut Vec<u8>,
) -> io::Result<()> {
match out.diverge() {}
}
#[allow(dead_code)]
mod uefi_command_internal {
use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output};

View file

@ -10,14 +10,15 @@ use crate::ffi::{CStr, CString, OsStr, OsString};
use crate::os::unix::prelude::*;
use crate::path::Path;
use crate::process::StdioPipes;
use crate::sys::cvt_r;
use crate::sys::fd::FileDesc;
use crate::sys::fs::File;
#[cfg(not(target_os = "fuchsia"))]
use crate::sys::fs::OpenOptions;
use crate::sys::pipe::{self, AnonPipe};
use crate::sys::pipe::pipe;
use crate::sys::process::env::{CommandEnv, CommandEnvs};
use crate::sys_common::{FromInner, IntoInner};
use crate::{fmt, io};
use crate::{fmt, io, mem};
mod cstring_array;
@ -393,7 +394,7 @@ fn construct_envp(env: BTreeMap<OsString, OsString>, saw_nul: &mut bool) -> CStr
}
impl Stdio {
pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option<AnonPipe>)> {
pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option<ChildPipe>)> {
match *self {
Stdio::Inherit => Ok((ChildStdio::Inherit, None)),
@ -418,9 +419,9 @@ impl Stdio {
}
Stdio::MakePipe => {
let (reader, writer) = pipe::anon_pipe()?;
let (reader, writer) = pipe()?;
let (ours, theirs) = if readable { (writer, reader) } else { (reader, writer) };
Ok((ChildStdio::Owned(theirs.into_inner()), Some(ours)))
Ok((ChildStdio::Owned(theirs), Some(ours)))
}
#[cfg(not(target_os = "fuchsia"))]
@ -438,12 +439,6 @@ impl Stdio {
}
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
Stdio::Fd(pipe.into_inner())
}
}
impl From<FileDesc> for Stdio {
fn from(fd: FileDesc) -> Stdio {
Stdio::Fd(fd)
@ -632,3 +627,56 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
f.debug_list().entries(self.iter.clone()).finish()
}
}
pub type ChildPipe = crate::sys::pipe::Pipe;
pub fn read_output(
out: ChildPipe,
stdout: &mut Vec<u8>,
err: ChildPipe,
stderr: &mut Vec<u8>,
) -> io::Result<()> {
// Set both pipes into nonblocking mode as we're gonna be reading from both
// in the `select` loop below, and we wouldn't want one to block the other!
out.set_nonblocking(true)?;
err.set_nonblocking(true)?;
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
fds[0].fd = out.as_raw_fd();
fds[0].events = libc::POLLIN;
fds[1].fd = err.as_raw_fd();
fds[1].events = libc::POLLIN;
loop {
// wait for either pipe to become readable using `poll`
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
if fds[0].revents != 0 && read(&out, stdout)? {
err.set_nonblocking(false)?;
return err.read_to_end(stderr).map(drop);
}
if fds[1].revents != 0 && read(&err, stderr)? {
out.set_nonblocking(false)?;
return out.read_to_end(stdout).map(drop);
}
}
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
// EAGAIN. If we hit EOF, then this will happen because the underlying
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
// this case we flip the other fd back into blocking mode and read
// whatever's leftover on that file descriptor.
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
match fd.read_to_end(dst) {
Ok(_) => Ok(true),
Err(e) => {
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|| e.raw_os_error() == Some(libc::EAGAIN)
{
Ok(false)
} else {
Err(e)
}
}
}
}
}

View file

@ -23,5 +23,5 @@ cfg_select! {
pub use imp::{ExitStatus, ExitStatusError, Process};
pub use self::common::{Command, CommandArgs, ExitCode, Stdio};
pub use self::common::{ChildPipe, Command, CommandArgs, ExitCode, Stdio, read_output};
pub use crate::ffi::OsString as EnvKey;

View file

@ -78,7 +78,7 @@ impl Command {
let (input, output) = sys::net::Socket::new_pair(libc::AF_UNIX, libc::SOCK_SEQPACKET)?;
#[cfg(not(target_os = "linux"))]
let (input, output) = sys::pipe::anon_pipe()?;
let (input, output) = sys::pipe::pipe()?;
// Whatever happens after the fork is almost for sure going to touch or
// look at the environment in one way or another (PATH in `execvp` or

View file

@ -5,7 +5,6 @@ use crate::num::NonZero;
use crate::path::Path;
use crate::process::StdioPipes;
use crate::sys::fs::File;
use crate::sys::pipe::AnonPipe;
use crate::sys::unsupported;
use crate::{fmt, io};
@ -107,8 +106,8 @@ pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)>
unsupported()
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
impl From<ChildPipe> for Stdio {
fn from(pipe: ChildPipe) -> Stdio {
pipe.diverge()
}
}
@ -317,3 +316,14 @@ impl<'a> fmt::Debug for CommandArgs<'a> {
f.debug_list().entries(self.iter.clone()).finish()
}
}
pub type ChildPipe = crate::sys::pipe::Pipe;
pub fn read_output(
out: ChildPipe,
_stdout: &mut Vec<u8>,
_err: ChildPipe,
_stderr: &mut Vec<u8>,
) -> io::Result<()> {
match out.diverge() {}
}

View file

@ -23,11 +23,14 @@ use crate::sys::fs::{File, OpenOptions};
use crate::sys::handle::Handle;
use crate::sys::pal::api::{self, WinError, utf16};
use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf};
use crate::sys::pipe::{self, AnonPipe};
use crate::sys::{cvt, path, stdio};
use crate::sys_common::IntoInner;
use crate::{cmp, env, fmt, ptr};
mod child_pipe;
pub use self::child_pipe::{ChildPipe, read_output};
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
@ -167,7 +170,7 @@ pub enum Stdio {
InheritSpecific { from_stdio_id: u32 },
Null,
MakePipe,
Pipe(AnonPipe),
Pipe(ChildPipe),
Handle(Handle),
}
@ -596,7 +599,7 @@ fn program_exists(path: &Path) -> Option<Vec<u16>> {
}
impl Stdio {
fn to_handle(&self, stdio_id: u32, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> {
fn to_handle(&self, stdio_id: u32, pipe: &mut Option<ChildPipe>) -> io::Result<Handle> {
let use_stdio_id = |stdio_id| match stdio::get_handle(stdio_id) {
Ok(io) => unsafe {
let io = Handle::from_raw_handle(io);
@ -613,14 +616,15 @@ impl Stdio {
Stdio::MakePipe => {
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
let pipes = pipe::anon_pipe(ours_readable, true)?;
let pipes = child_pipe::child_pipe(ours_readable, true)?;
*pipe = Some(pipes.ours);
Ok(pipes.theirs.into_handle())
}
Stdio::Pipe(ref source) => {
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
pipe::spawn_pipe_relay(source, ours_readable, true).map(AnonPipe::into_handle)
child_pipe::spawn_pipe_relay(source, ours_readable, true)
.map(ChildPipe::into_handle)
}
Stdio::Handle(ref handle) => handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS),
@ -639,8 +643,8 @@ impl Stdio {
}
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
impl From<ChildPipe> for Stdio {
fn from(pipe: ChildPipe) -> Stdio {
Stdio::Pipe(pipe)
}
}

View file

@ -6,39 +6,37 @@ use crate::sys::{api, c};
use crate::sys_common::{FromInner, IntoInner};
use crate::{mem, ptr};
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
////////////////////////////////////////////////////////////////////////////////
pub struct AnonPipe {
pub struct ChildPipe {
inner: Handle,
}
impl IntoInner<Handle> for AnonPipe {
impl IntoInner<Handle> for ChildPipe {
fn into_inner(self) -> Handle {
self.inner
}
}
impl FromInner<Handle> for AnonPipe {
fn from_inner(inner: Handle) -> AnonPipe {
impl FromInner<Handle> for ChildPipe {
fn from_inner(inner: Handle) -> ChildPipe {
Self { inner }
}
}
pub struct Pipes {
pub ours: AnonPipe,
pub theirs: AnonPipe,
pub(super) struct Pipes {
pub ours: ChildPipe,
pub theirs: ChildPipe,
}
/// Although this looks similar to `anon_pipe` in the Unix module it's actually
/// subtly different. Here we'll return two pipes in the `Pipes` return value,
/// but one is intended for "us" where as the other is intended for "someone
/// else".
/// Creates an anonymous pipe suitable for communication with a child process.
///
/// Currently the only use case for this function is pipes for stdio on
/// processes in the standard library, so "ours" is the one that'll stay in our
/// process whereas "theirs" will be inherited to a child.
/// Windows unfortunately does not have a way of performing asynchronous operations
/// on a handle originally created for synchronous operation. As `read_output` can
/// only be correctly implemented with asynchronous reads but the pipe created by
/// `CreatePipe` is synchronous, we cannot use it (and thus [`io::pipe`]) to create
/// a pipe for communicating with a child. Instead, this function uses the NT API
/// to create a pipe where one pipe handle (`ours`) is asynchronous and one is
/// synchronous and can be inherited by a child for use as a console handle
/// (`theirs`).
///
/// The ours/theirs pipes are *not* specifically readable or writable. Each
/// one only supports a read or a write, but which is which depends on the
@ -50,7 +48,11 @@ pub struct Pipes {
/// mode. This means that technically speaking it should only ever be used
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
/// once at a time (which we do indeed guarantee).
pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
// FIXME(joboet): No, we don't guarantee that? E.g. `&Stdout` is both `Read`
// and `Sync`, so there could be multiple operations at the same
// time. All the functions below that forward to the inner handle
// methods could abort if used concurrently.
pub(super) fn child_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
// A 64kb pipe capacity is the same as a typical Linux default.
const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024;
@ -166,7 +168,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
}
};
Ok(Pipes { ours: AnonPipe { inner: ours }, theirs: AnonPipe { inner: theirs } })
Ok(Pipes { ours: ChildPipe { inner: ours }, theirs: ChildPipe { inner: theirs } })
}
}
@ -175,16 +177,16 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
///
/// This is achieved by creating a new set of pipes and spawning a thread that
/// relays messages between the source and the synchronous pipe.
pub fn spawn_pipe_relay(
source: &AnonPipe,
pub(super) fn spawn_pipe_relay(
source: &ChildPipe,
ours_readable: bool,
their_handle_inheritable: bool,
) -> io::Result<AnonPipe> {
) -> io::Result<ChildPipe> {
// We need this handle to live for the lifetime of the thread spawned below.
let source = source.try_clone()?;
// create a new pair of anon pipes.
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
let Pipes { theirs, ours } = child_pipe(ours_readable, their_handle_inheritable)?;
// Spawn a thread that passes messages from one pipe to the other.
// Any errors will simply cause the thread to exit.
@ -210,7 +212,7 @@ pub fn spawn_pipe_relay(
Ok(theirs)
}
impl AnonPipe {
impl ChildPipe {
pub fn handle(&self) -> &Handle {
&self.inner
}
@ -219,7 +221,7 @@ impl AnonPipe {
}
pub fn try_clone(&self) -> io::Result<Self> {
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| ChildPipe { inner })
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
@ -347,18 +349,17 @@ impl AnonPipe {
// STEP 3: The callback.
unsafe extern "system" fn callback(
dwErrorCode: u32,
dwNumberOfBytesTransferred: u32,
lpOverlapped: *mut c::OVERLAPPED,
error: u32,
transferred: u32,
overlapped: *mut c::OVERLAPPED,
) {
// Set `async_result` using a pointer smuggled through `hEvent`.
// SAFETY:
// At this point, the OVERLAPPED struct will have been written to by the OS,
// except for our `hEvent` field which we set to a valid AsyncResult pointer (see below)
unsafe {
let result =
AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred };
*(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
let result = AsyncResult { error, transferred };
*(*overlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result);
}
}
@ -395,7 +396,12 @@ impl AnonPipe {
}
}
pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
pub fn read_output(
p1: ChildPipe,
v1: &mut Vec<u8>,
p2: ChildPipe,
v2: &mut Vec<u8>,
) -> io::Result<()> {
let p1 = p1.into_handle();
let p2 = p2.into_handle();

View file

@ -166,7 +166,7 @@ impl From<crate::process::ChildStdin> for OwnedFd {
impl From<OwnedFd> for process::ChildStdin {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStdin {
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = sys::process::ChildPipe::from_inner(fd);
process::ChildStdin::from_inner(pipe)
}
}
@ -196,7 +196,7 @@ impl From<crate::process::ChildStdout> for OwnedFd {
impl From<OwnedFd> for process::ChildStdout {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStdout {
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = sys::process::ChildPipe::from_inner(fd);
process::ChildStdout::from_inner(pipe)
}
}
@ -226,7 +226,7 @@ impl From<crate::process::ChildStderr> for OwnedFd {
impl From<OwnedFd> for process::ChildStderr {
#[inline]
fn from(fd: OwnedFd) -> process::ChildStderr {
let pipe = sys::pipe::AnonPipe::from_inner(fd);
let pipe = sys::process::ChildPipe::from_inner(fd);
process::ChildStderr::from_inner(pipe)
}
}