mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 05:56:56 +00:00
Auto merge of #127153 - NobodyXu:pipe, r=ChrisDenton
Initial implementation of anonymous_pipe API ACP completed in rust-lang/libs-team#375 Tracking issue: #127154 try-job: x86_64-msvc try-job: i686-mingw
This commit is contained in:
commit
f751af4d78
@ -20,8 +20,12 @@ core = { path = "../core", public = true }
|
||||
compiler_builtins = { version = "0.1.105" }
|
||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||
unwind = { path = "../unwind" }
|
||||
hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
hashbrown = { version = "0.14", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
] }
|
||||
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
] }
|
||||
|
||||
# Dependencies of the `backtrace` crate
|
||||
rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] }
|
||||
@ -31,13 +35,27 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
|
||||
addr2line = { version = "0.22.0", optional = true, default-features = false }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
|
||||
libc = { version = "0.2.153", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
], public = true }
|
||||
|
||||
[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = [
|
||||
'read_core',
|
||||
'elf',
|
||||
'macho',
|
||||
'pe',
|
||||
'unaligned',
|
||||
'archive',
|
||||
] }
|
||||
|
||||
[target.'cfg(target_os = "aix")'.dependencies]
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] }
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = [
|
||||
'read_core',
|
||||
'xcoff',
|
||||
'unaligned',
|
||||
'archive',
|
||||
] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
|
||||
@ -47,13 +65,19 @@ rand_xorshift = "0.3.0"
|
||||
dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[target.x86_64-fortanix-unknown-sgx.dependencies]
|
||||
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
|
||||
fortanix-sgx-abi = { version = "0.5.0", features = [
|
||||
'rustc-dep-of-std',
|
||||
], public = true }
|
||||
|
||||
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||
hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }
|
||||
hermit-abi = { version = "0.4.0", features = [
|
||||
'rustc-dep-of-std',
|
||||
], public = true }
|
||||
|
||||
[target.'cfg(target_os = "wasi")'.dependencies]
|
||||
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
|
||||
wasi = { version = "0.11.0", features = [
|
||||
'rustc-dep-of-std',
|
||||
], default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "uefi")'.dependencies]
|
||||
r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
|
||||
@ -61,9 +85,9 @@ r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[features]
|
||||
backtrace = [
|
||||
'addr2line/rustc-dep-of-std',
|
||||
'object/rustc-dep-of-std',
|
||||
'miniz_oxide/rustc-dep-of-std',
|
||||
'addr2line/rustc-dep-of-std',
|
||||
'object/rustc-dep-of-std',
|
||||
'miniz_oxide/rustc-dep-of-std',
|
||||
]
|
||||
|
||||
panic-unwind = ["panic_unwind"]
|
||||
@ -77,7 +101,10 @@ llvm-libunwind = ["unwind/llvm-libunwind"]
|
||||
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
|
||||
|
||||
# Make panics and failed asserts immediately abort without formatting any message
|
||||
panic_immediate_abort = ["core/panic_immediate_abort", "alloc/panic_immediate_abort"]
|
||||
panic_immediate_abort = [
|
||||
"core/panic_immediate_abort",
|
||||
"alloc/panic_immediate_abort",
|
||||
]
|
||||
# Choose algorithms that are optimized for binary size instead of runtime performance
|
||||
optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
|
||||
|
||||
@ -97,6 +124,11 @@ threads = 125
|
||||
# Maximum heap size
|
||||
heap_size = 0x8000000
|
||||
|
||||
[[test]]
|
||||
name = "pipe-subprocess"
|
||||
path = "tests/pipe_subprocess.rs"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "stdbenches"
|
||||
path = "benches/lib.rs"
|
||||
|
@ -591,6 +591,8 @@ pub mod panic;
|
||||
#[unstable(feature = "core_pattern_types", issue = "none")]
|
||||
pub mod pat;
|
||||
pub mod path;
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
pub mod pipe;
|
||||
pub mod process;
|
||||
pub mod sync;
|
||||
pub mod time;
|
||||
|
130
library/std/src/pipe.rs
Normal file
130
library/std/src/pipe.rs
Normal file
@ -0,0 +1,130 @@
|
||||
//! Module for anonymous pipe
|
||||
//!
|
||||
//! ```
|
||||
//! #![feature(anonymous_pipe)]
|
||||
//!
|
||||
//! # #[cfg(miri)] fn main() {}
|
||||
//! # #[cfg(not(miri))]
|
||||
//! # fn main() -> std::io::Result<()> {
|
||||
//! let (reader, writer) = std::pipe::pipe()?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
use crate::{
|
||||
io,
|
||||
sys::anonymous_pipe::{pipe as pipe_inner, AnonPipe},
|
||||
};
|
||||
|
||||
/// Create anonymous pipe that is close-on-exec and blocking.
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
#[inline]
|
||||
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
|
||||
pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
|
||||
}
|
||||
|
||||
/// Read end of the anonymous pipe.
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
#[derive(Debug)]
|
||||
pub struct PipeReader(pub(crate) AnonPipe);
|
||||
|
||||
/// Write end of the anonymous pipe.
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
#[derive(Debug)]
|
||||
pub struct PipeWriter(pub(crate) AnonPipe);
|
||||
|
||||
impl PipeReader {
|
||||
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.0.try_clone().map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl PipeWriter {
|
||||
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.0.try_clone().map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl io::Read for &PipeReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
#[inline]
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0.read_buf(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl io::Read for PipeReader {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
#[inline]
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0.read_buf(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl io::Write for &PipeWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl io::Write for PipeWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
}
|
18
library/std/src/sys/anonymous_pipe/mod.rs
Normal file
18
library/std/src/sys/anonymous_pipe/mod.rs
Normal file
@ -0,0 +1,18 @@
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
mod unix;
|
||||
pub(crate) use unix::{AnonPipe, pipe};
|
||||
|
||||
#[cfg(all(test, not(miri)))]
|
||||
mod tests;
|
||||
} else if #[cfg(windows)] {
|
||||
mod windows;
|
||||
pub(crate) use windows::{AnonPipe, pipe};
|
||||
|
||||
#[cfg(all(test, not(miri)))]
|
||||
mod tests;
|
||||
} else {
|
||||
mod unsupported;
|
||||
pub(crate) use unsupported::{AnonPipe, pipe};
|
||||
}
|
||||
}
|
20
library/std/src/sys/anonymous_pipe/tests.rs
Normal file
20
library/std/src/sys/anonymous_pipe/tests.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::{
|
||||
io::{Read, Write},
|
||||
pipe::pipe,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn pipe_creation_clone_and_rw() {
|
||||
let (rx, tx) = pipe().unwrap();
|
||||
|
||||
tx.try_clone().unwrap().write_all(b"12345").unwrap();
|
||||
drop(tx);
|
||||
|
||||
let mut rx2 = rx.try_clone().unwrap();
|
||||
drop(rx);
|
||||
|
||||
let mut s = String::new();
|
||||
rx2.read_to_string(&mut s).unwrap();
|
||||
drop(rx2);
|
||||
assert_eq!(s, "12345");
|
||||
}
|
103
library/std/src/sys/anonymous_pipe/unix.rs
Normal file
103
library/std/src/sys/anonymous_pipe/unix.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use crate::{
|
||||
io,
|
||||
os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
|
||||
pipe::{PipeReader, PipeWriter},
|
||||
process::Stdio,
|
||||
sys::{fd::FileDesc, pipe::anon_pipe},
|
||||
sys_common::{FromInner, IntoInner},
|
||||
};
|
||||
|
||||
pub(crate) type AnonPipe = FileDesc;
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsFd for PipeReader {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsRawFd for PipeReader {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeReader> for OwnedFd {
|
||||
fn from(pipe: PipeReader) -> Self {
|
||||
FileDesc::into_inner(pipe.0)
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl FromRawFd for PipeReader {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FileDesc::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl IntoRawFd for PipeReader {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeReader> for Stdio {
|
||||
fn from(pipe: PipeReader) -> Self {
|
||||
Self::from(OwnedFd::from(pipe))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsFd for PipeWriter {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.0.as_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsRawFd for PipeWriter {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0.as_raw_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeWriter> for OwnedFd {
|
||||
fn from(pipe: PipeWriter) -> Self {
|
||||
FileDesc::into_inner(pipe.0)
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl FromRawFd for PipeWriter {
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self(FileDesc::from_raw_fd(raw_fd))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl IntoRawFd for PipeWriter {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.0.into_raw_fd()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeWriter> for Stdio {
|
||||
fn from(pipe: PipeWriter) -> Self {
|
||||
Self::from(OwnedFd::from(pipe))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<OwnedFd> for PipeReader {
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self(FileDesc::from_inner(owned_fd))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<OwnedFd> for PipeWriter {
|
||||
fn from(owned_fd: OwnedFd) -> Self {
|
||||
Self(FileDesc::from_inner(owned_fd))
|
||||
}
|
||||
}
|
26
library/std/src/sys/anonymous_pipe/unsupported.rs
Normal file
26
library/std/src/sys/anonymous_pipe/unsupported.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::{
|
||||
io,
|
||||
pipe::{PipeReader, PipeWriter},
|
||||
process::Stdio,
|
||||
};
|
||||
|
||||
pub(crate) use crate::sys::pipe::AnonPipe;
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeReader> for Stdio {
|
||||
fn from(pipe: PipeReader) -> Self {
|
||||
pipe.0.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeWriter> for Stdio {
|
||||
fn from(pipe: PipeWriter) -> Self {
|
||||
pipe.0.diverge()
|
||||
}
|
||||
}
|
109
library/std/src/sys/anonymous_pipe/windows.rs
Normal file
109
library/std/src/sys/anonymous_pipe/windows.rs
Normal file
@ -0,0 +1,109 @@
|
||||
use crate::{
|
||||
io,
|
||||
os::windows::io::{
|
||||
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
|
||||
},
|
||||
pipe::{PipeReader, PipeWriter},
|
||||
process::Stdio,
|
||||
sys::{handle::Handle, pipe::unnamed_anon_pipe},
|
||||
sys_common::{FromInner, IntoInner},
|
||||
};
|
||||
|
||||
pub(crate) type AnonPipe = Handle;
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
unnamed_anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsHandle for PipeReader {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.0.as_handle()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsRawHandle for PipeReader {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.0.as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl FromRawHandle for PipeReader {
|
||||
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
|
||||
Self(Handle::from_raw_handle(raw_handle))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl IntoRawHandle for PipeReader {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.0.into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeReader> for OwnedHandle {
|
||||
fn from(pipe: PipeReader) -> Self {
|
||||
Handle::into_inner(pipe.0)
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeReader> for Stdio {
|
||||
fn from(pipe: PipeReader) -> Self {
|
||||
Self::from(OwnedHandle::from(pipe))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsHandle for PipeWriter {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
self.0.as_handle()
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl AsRawHandle for PipeWriter {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
self.0.as_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl FromRawHandle for PipeWriter {
|
||||
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
|
||||
Self(Handle::from_raw_handle(raw_handle))
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl IntoRawHandle for PipeWriter {
|
||||
fn into_raw_handle(self) -> RawHandle {
|
||||
self.0.into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeWriter> for OwnedHandle {
|
||||
fn from(pipe: PipeWriter) -> Self {
|
||||
Handle::into_inner(pipe.0)
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<PipeWriter> for Stdio {
|
||||
fn from(pipe: PipeWriter) -> Self {
|
||||
Self::from(OwnedHandle::from(pipe))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<OwnedHandle> for PipeReader {
|
||||
fn from(owned_handle: OwnedHandle) -> Self {
|
||||
Self(Handle::from_inner(owned_handle))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
impl From<OwnedHandle> for PipeWriter {
|
||||
fn from(owned_handle: OwnedHandle) -> Self {
|
||||
Self(Handle::from_inner(owned_handle))
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ mod pal;
|
||||
|
||||
mod personality;
|
||||
|
||||
#[unstable(feature = "anonymous_pipe", issue = "127154")]
|
||||
pub mod anonymous_pipe;
|
||||
pub mod backtrace;
|
||||
pub mod cmath;
|
||||
pub mod exit_guard;
|
||||
|
@ -82,6 +82,11 @@ const fn max_iov() -> usize {
|
||||
}
|
||||
|
||||
impl FileDesc {
|
||||
#[inline]
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.duplicate()
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
libc::read(
|
||||
|
@ -9,6 +9,7 @@ use crate::sys_common::{FromInner, IntoInner};
|
||||
// Anonymous pipes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnonPipe(FileDesc);
|
||||
|
||||
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
@ -46,6 +47,10 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
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)
|
||||
}
|
||||
@ -79,6 +84,10 @@ impl AnonPipe {
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
|
||||
pub fn as_file_desc(&self) -> &FileDesc {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoInner<FileDesc> for AnonPipe {
|
||||
|
@ -1,8 +1,21 @@
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::{
|
||||
fmt,
|
||||
io::{self, BorrowedCursor, IoSlice, IoSliceMut},
|
||||
};
|
||||
|
||||
pub struct AnonPipe(!);
|
||||
|
||||
impl fmt::Debug for AnonPipe {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
@ -2463,6 +2463,7 @@ Windows.Win32.System.LibraryLoader.GetProcAddress
|
||||
Windows.Win32.System.Performance.QueryPerformanceCounter
|
||||
Windows.Win32.System.Performance.QueryPerformanceFrequency
|
||||
Windows.Win32.System.Pipes.CreateNamedPipeW
|
||||
Windows.Win32.System.Pipes.CreatePipe
|
||||
Windows.Win32.System.Pipes.NAMED_PIPE_MODE
|
||||
Windows.Win32.System.Pipes.PIPE_ACCEPT_REMOTE_CLIENTS
|
||||
Windows.Win32.System.Pipes.PIPE_CLIENT_END
|
||||
|
@ -14,6 +14,7 @@ windows_targets::link!("kernel32.dll" "system" fn CreateEventW(lpeventattributes
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateFileW(lpfilename : PCWSTR, dwdesiredaccess : u32, dwsharemode : FILE_SHARE_MODE, lpsecurityattributes : *const SECURITY_ATTRIBUTES, dwcreationdisposition : FILE_CREATION_DISPOSITION, dwflagsandattributes : FILE_FLAGS_AND_ATTRIBUTES, htemplatefile : HANDLE) -> HANDLE);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateHardLinkW(lpfilename : PCWSTR, lpexistingfilename : PCWSTR, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> BOOL);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateNamedPipeW(lpname : PCWSTR, dwopenmode : FILE_FLAGS_AND_ATTRIBUTES, dwpipemode : NAMED_PIPE_MODE, nmaxinstances : u32, noutbuffersize : u32, ninbuffersize : u32, ndefaulttimeout : u32, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> HANDLE);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreatePipe(hreadpipe : *mut HANDLE, hwritepipe : *mut HANDLE, lppipeattributes : *const SECURITY_ATTRIBUTES, nsize : u32) -> BOOL);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateProcessW(lpapplicationname : PCWSTR, lpcommandline : PWSTR, lpprocessattributes : *const SECURITY_ATTRIBUTES, lpthreadattributes : *const SECURITY_ATTRIBUTES, binherithandles : BOOL, dwcreationflags : PROCESS_CREATION_FLAGS, lpenvironment : *const core::ffi::c_void, lpcurrentdirectory : PCWSTR, lpstartupinfo : *const STARTUPINFOW, lpprocessinformation : *mut PROCESS_INFORMATION) -> BOOL);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateSymbolicLinkW(lpsymlinkfilename : PCWSTR, lptargetfilename : PCWSTR, dwflags : SYMBOLIC_LINK_FLAGS) -> BOOLEAN);
|
||||
windows_targets::link!("kernel32.dll" "system" fn CreateThread(lpthreadattributes : *const SECURITY_ATTRIBUTES, dwstacksize : usize, lpstartaddress : LPTHREAD_START_ROUTINE, lpparameter : *const core::ffi::c_void, dwcreationflags : THREAD_CREATION_FLAGS, lpthreadid : *mut u32) -> HANDLE);
|
||||
|
@ -17,6 +17,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
/// An owned container for `HANDLE` object, closing them on Drop.
|
||||
///
|
||||
/// All methods are inherited through a `Deref` impl to `RawHandle`
|
||||
#[derive(Debug)]
|
||||
pub struct Handle(OwnedHandle);
|
||||
|
||||
impl Handle {
|
||||
@ -136,6 +137,12 @@ impl Handle {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
let mut me = self;
|
||||
|
||||
Read::read_to_end(&mut me, buf)
|
||||
}
|
||||
|
||||
pub unsafe fn read_overlapped(
|
||||
&self,
|
||||
buf: &mut [mem::MaybeUninit<u8>],
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::os::windows::prelude::*;
|
||||
|
||||
use crate::ffi::OsStr;
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::mem;
|
||||
use crate::path::Path;
|
||||
use crate::ptr;
|
||||
@ -39,6 +39,23 @@ pub struct Pipes {
|
||||
pub theirs: AnonPipe,
|
||||
}
|
||||
|
||||
/// Create true unnamed anonymous pipe.
|
||||
pub fn unnamed_anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||
let mut read_pipe = c::INVALID_HANDLE_VALUE;
|
||||
let mut write_pipe = c::INVALID_HANDLE_VALUE;
|
||||
|
||||
let ret = unsafe { c::CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) };
|
||||
|
||||
if ret == 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok((
|
||||
AnonPipe::from_inner(unsafe { Handle::from_raw_handle(read_pipe) }),
|
||||
AnonPipe::from_inner(unsafe { Handle::from_raw_handle(write_pipe) }),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -181,7 +198,7 @@ pub fn spawn_pipe_relay(
|
||||
their_handle_inheritable: bool,
|
||||
) -> io::Result<AnonPipe> {
|
||||
// We need this handle to live for the lifetime of the thread spawned below.
|
||||
let source = source.duplicate()?;
|
||||
let source = source.try_clone()?;
|
||||
|
||||
// create a new pair of anon pipes.
|
||||
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
|
||||
@ -237,7 +254,8 @@ impl AnonPipe {
|
||||
pub fn into_handle(self) -> Handle {
|
||||
self.inner
|
||||
}
|
||||
fn duplicate(&self) -> io::Result<Self> {
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
|
||||
}
|
||||
|
||||
|
39
library/std/tests/pipe_subprocess.rs
Normal file
39
library/std/tests/pipe_subprocess.rs
Normal file
@ -0,0 +1,39 @@
|
||||
#![feature(anonymous_pipe)]
|
||||
|
||||
fn main() {
|
||||
#[cfg(all(not(miri), any(unix, windows)))]
|
||||
{
|
||||
use std::{env, io::Read, pipe::pipe, process};
|
||||
|
||||
if env::var("I_AM_THE_CHILD").is_ok() {
|
||||
child();
|
||||
} else {
|
||||
parent();
|
||||
}
|
||||
|
||||
fn parent() {
|
||||
let me = env::current_exe().unwrap();
|
||||
|
||||
let (rx, tx) = pipe().unwrap();
|
||||
assert!(
|
||||
process::Command::new(me)
|
||||
.env("I_AM_THE_CHILD", "1")
|
||||
.stdout(tx)
|
||||
.status()
|
||||
.unwrap()
|
||||
.success()
|
||||
);
|
||||
|
||||
let mut s = String::new();
|
||||
(&rx).read_to_string(&mut s).unwrap();
|
||||
drop(rx);
|
||||
assert_eq!(s, "Heloo,\n");
|
||||
|
||||
println!("Test pipe_subprocess.rs success");
|
||||
}
|
||||
|
||||
fn child() {
|
||||
println!("Heloo,");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user