Skip to content

Commit f751af4

Browse files
committed
Auto merge of rust-lang#127153 - NobodyXu:pipe, r=ChrisDenton
Initial implementation of anonymous_pipe API ACP completed in rust-lang/libs-team#375 Tracking issue: rust-lang#127154 try-job: x86_64-msvc try-job: i686-mingw
2 parents 8bfcae7 + c9c8a14 commit f751af4

File tree

17 files changed

+551
-16
lines changed

17 files changed

+551
-16
lines changed

library/std/Cargo.toml

+44-12
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ core = { path = "../core", public = true }
2020
compiler_builtins = { version = "0.1.105" }
2121
profiler_builtins = { path = "../profiler_builtins", optional = true }
2222
unwind = { path = "../unwind" }
23-
hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
24-
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = ['rustc-dep-of-std'] }
23+
hashbrown = { version = "0.14", default-features = false, features = [
24+
'rustc-dep-of-std',
25+
] }
26+
std_detect = { path = "../stdarch/crates/std_detect", default-features = false, features = [
27+
'rustc-dep-of-std',
28+
] }
2529

2630
# Dependencies of the `backtrace` crate
2731
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 }
3135
addr2line = { version = "0.22.0", optional = true, default-features = false }
3236

3337
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
34-
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
38+
libc = { version = "0.2.153", default-features = false, features = [
39+
'rustc-dep-of-std',
40+
], public = true }
3541

3642
[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
37-
object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
43+
object = { version = "0.36.0", default-features = false, optional = true, features = [
44+
'read_core',
45+
'elf',
46+
'macho',
47+
'pe',
48+
'unaligned',
49+
'archive',
50+
] }
3851

3952
[target.'cfg(target_os = "aix")'.dependencies]
40-
object = { version = "0.36.0", default-features = false, optional = true, features = ['read_core', 'xcoff', 'unaligned', 'archive'] }
53+
object = { version = "0.36.0", default-features = false, optional = true, features = [
54+
'read_core',
55+
'xcoff',
56+
'unaligned',
57+
'archive',
58+
] }
4159

4260
[dev-dependencies]
4361
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
@@ -47,23 +65,29 @@ rand_xorshift = "0.3.0"
4765
dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
4866

4967
[target.x86_64-fortanix-unknown-sgx.dependencies]
50-
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
68+
fortanix-sgx-abi = { version = "0.5.0", features = [
69+
'rustc-dep-of-std',
70+
], public = true }
5171

5272
[target.'cfg(target_os = "hermit")'.dependencies]
53-
hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }
73+
hermit-abi = { version = "0.4.0", features = [
74+
'rustc-dep-of-std',
75+
], public = true }
5476

5577
[target.'cfg(target_os = "wasi")'.dependencies]
56-
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
78+
wasi = { version = "0.11.0", features = [
79+
'rustc-dep-of-std',
80+
], default-features = false }
5781

5882
[target.'cfg(target_os = "uefi")'.dependencies]
5983
r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
6084
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }
6185

6286
[features]
6387
backtrace = [
64-
'addr2line/rustc-dep-of-std',
65-
'object/rustc-dep-of-std',
66-
'miniz_oxide/rustc-dep-of-std',
88+
'addr2line/rustc-dep-of-std',
89+
'object/rustc-dep-of-std',
90+
'miniz_oxide/rustc-dep-of-std',
6791
]
6892

6993
panic-unwind = ["panic_unwind"]
@@ -77,7 +101,10 @@ llvm-libunwind = ["unwind/llvm-libunwind"]
77101
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
78102

79103
# Make panics and failed asserts immediately abort without formatting any message
80-
panic_immediate_abort = ["core/panic_immediate_abort", "alloc/panic_immediate_abort"]
104+
panic_immediate_abort = [
105+
"core/panic_immediate_abort",
106+
"alloc/panic_immediate_abort",
107+
]
81108
# Choose algorithms that are optimized for binary size instead of runtime performance
82109
optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
83110

@@ -97,6 +124,11 @@ threads = 125
97124
# Maximum heap size
98125
heap_size = 0x8000000
99126

127+
[[test]]
128+
name = "pipe-subprocess"
129+
path = "tests/pipe_subprocess.rs"
130+
harness = false
131+
100132
[[bench]]
101133
name = "stdbenches"
102134
path = "benches/lib.rs"

library/std/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ pub mod panic;
591591
#[unstable(feature = "core_pattern_types", issue = "none")]
592592
pub mod pat;
593593
pub mod path;
594+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
595+
pub mod pipe;
594596
pub mod process;
595597
pub mod sync;
596598
pub mod time;

library/std/src/pipe.rs

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//! Module for anonymous pipe
2+
//!
3+
//! ```
4+
//! #![feature(anonymous_pipe)]
5+
//!
6+
//! # #[cfg(miri)] fn main() {}
7+
//! # #[cfg(not(miri))]
8+
//! # fn main() -> std::io::Result<()> {
9+
//! let (reader, writer) = std::pipe::pipe()?;
10+
//! # Ok(())
11+
//! # }
12+
//! ```
13+
14+
use crate::{
15+
io,
16+
sys::anonymous_pipe::{pipe as pipe_inner, AnonPipe},
17+
};
18+
19+
/// Create anonymous pipe that is close-on-exec and blocking.
20+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
21+
#[inline]
22+
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
23+
pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer)))
24+
}
25+
26+
/// Read end of the anonymous pipe.
27+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
28+
#[derive(Debug)]
29+
pub struct PipeReader(pub(crate) AnonPipe);
30+
31+
/// Write end of the anonymous pipe.
32+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
33+
#[derive(Debug)]
34+
pub struct PipeWriter(pub(crate) AnonPipe);
35+
36+
impl PipeReader {
37+
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
38+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
39+
pub fn try_clone(&self) -> io::Result<Self> {
40+
self.0.try_clone().map(Self)
41+
}
42+
}
43+
44+
impl PipeWriter {
45+
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
46+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
47+
pub fn try_clone(&self) -> io::Result<Self> {
48+
self.0.try_clone().map(Self)
49+
}
50+
}
51+
52+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
53+
impl io::Read for &PipeReader {
54+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
55+
self.0.read(buf)
56+
}
57+
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
58+
self.0.read_vectored(bufs)
59+
}
60+
#[inline]
61+
fn is_read_vectored(&self) -> bool {
62+
self.0.is_read_vectored()
63+
}
64+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
65+
self.0.read_to_end(buf)
66+
}
67+
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
68+
self.0.read_buf(buf)
69+
}
70+
}
71+
72+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
73+
impl io::Read for PipeReader {
74+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
75+
self.0.read(buf)
76+
}
77+
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
78+
self.0.read_vectored(bufs)
79+
}
80+
#[inline]
81+
fn is_read_vectored(&self) -> bool {
82+
self.0.is_read_vectored()
83+
}
84+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
85+
self.0.read_to_end(buf)
86+
}
87+
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
88+
self.0.read_buf(buf)
89+
}
90+
}
91+
92+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
93+
impl io::Write for &PipeWriter {
94+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
95+
self.0.write(buf)
96+
}
97+
#[inline]
98+
fn flush(&mut self) -> io::Result<()> {
99+
Ok(())
100+
}
101+
102+
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
103+
self.0.write_vectored(bufs)
104+
}
105+
106+
#[inline]
107+
fn is_write_vectored(&self) -> bool {
108+
self.0.is_write_vectored()
109+
}
110+
}
111+
112+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
113+
impl io::Write for PipeWriter {
114+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
115+
self.0.write(buf)
116+
}
117+
#[inline]
118+
fn flush(&mut self) -> io::Result<()> {
119+
Ok(())
120+
}
121+
122+
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
123+
self.0.write_vectored(bufs)
124+
}
125+
126+
#[inline]
127+
fn is_write_vectored(&self) -> bool {
128+
self.0.is_write_vectored()
129+
}
130+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cfg_if::cfg_if! {
2+
if #[cfg(unix)] {
3+
mod unix;
4+
pub(crate) use unix::{AnonPipe, pipe};
5+
6+
#[cfg(all(test, not(miri)))]
7+
mod tests;
8+
} else if #[cfg(windows)] {
9+
mod windows;
10+
pub(crate) use windows::{AnonPipe, pipe};
11+
12+
#[cfg(all(test, not(miri)))]
13+
mod tests;
14+
} else {
15+
mod unsupported;
16+
pub(crate) use unsupported::{AnonPipe, pipe};
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use crate::{
2+
io::{Read, Write},
3+
pipe::pipe,
4+
};
5+
6+
#[test]
7+
fn pipe_creation_clone_and_rw() {
8+
let (rx, tx) = pipe().unwrap();
9+
10+
tx.try_clone().unwrap().write_all(b"12345").unwrap();
11+
drop(tx);
12+
13+
let mut rx2 = rx.try_clone().unwrap();
14+
drop(rx);
15+
16+
let mut s = String::new();
17+
rx2.read_to_string(&mut s).unwrap();
18+
drop(rx2);
19+
assert_eq!(s, "12345");
20+
}
+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use crate::{
2+
io,
3+
os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
4+
pipe::{PipeReader, PipeWriter},
5+
process::Stdio,
6+
sys::{fd::FileDesc, pipe::anon_pipe},
7+
sys_common::{FromInner, IntoInner},
8+
};
9+
10+
pub(crate) type AnonPipe = FileDesc;
11+
12+
#[inline]
13+
pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
14+
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
15+
}
16+
17+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
18+
impl AsFd for PipeReader {
19+
fn as_fd(&self) -> BorrowedFd<'_> {
20+
self.0.as_fd()
21+
}
22+
}
23+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
24+
impl AsRawFd for PipeReader {
25+
fn as_raw_fd(&self) -> RawFd {
26+
self.0.as_raw_fd()
27+
}
28+
}
29+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
30+
impl From<PipeReader> for OwnedFd {
31+
fn from(pipe: PipeReader) -> Self {
32+
FileDesc::into_inner(pipe.0)
33+
}
34+
}
35+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
36+
impl FromRawFd for PipeReader {
37+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
38+
Self(FileDesc::from_raw_fd(raw_fd))
39+
}
40+
}
41+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
42+
impl IntoRawFd for PipeReader {
43+
fn into_raw_fd(self) -> RawFd {
44+
self.0.into_raw_fd()
45+
}
46+
}
47+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
48+
impl From<PipeReader> for Stdio {
49+
fn from(pipe: PipeReader) -> Self {
50+
Self::from(OwnedFd::from(pipe))
51+
}
52+
}
53+
54+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
55+
impl AsFd for PipeWriter {
56+
fn as_fd(&self) -> BorrowedFd<'_> {
57+
self.0.as_fd()
58+
}
59+
}
60+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
61+
impl AsRawFd for PipeWriter {
62+
fn as_raw_fd(&self) -> RawFd {
63+
self.0.as_raw_fd()
64+
}
65+
}
66+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
67+
impl From<PipeWriter> for OwnedFd {
68+
fn from(pipe: PipeWriter) -> Self {
69+
FileDesc::into_inner(pipe.0)
70+
}
71+
}
72+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
73+
impl FromRawFd for PipeWriter {
74+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
75+
Self(FileDesc::from_raw_fd(raw_fd))
76+
}
77+
}
78+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
79+
impl IntoRawFd for PipeWriter {
80+
fn into_raw_fd(self) -> RawFd {
81+
self.0.into_raw_fd()
82+
}
83+
}
84+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
85+
impl From<PipeWriter> for Stdio {
86+
fn from(pipe: PipeWriter) -> Self {
87+
Self::from(OwnedFd::from(pipe))
88+
}
89+
}
90+
91+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
92+
impl From<OwnedFd> for PipeReader {
93+
fn from(owned_fd: OwnedFd) -> Self {
94+
Self(FileDesc::from_inner(owned_fd))
95+
}
96+
}
97+
98+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
99+
impl From<OwnedFd> for PipeWriter {
100+
fn from(owned_fd: OwnedFd) -> Self {
101+
Self(FileDesc::from_inner(owned_fd))
102+
}
103+
}

0 commit comments

Comments
 (0)