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

Rollup of 7 pull requests #136081

Closed
wants to merge 26 commits into from
Closed
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0d90d47
TRPL: more backward-compatible Edition changes
chriskrycho Jan 21, 2025
9cfc420
TRPL: integrate edits to Chapter 17
chriskrycho Jan 21, 2025
4d1c16c
Make the wasm_c_abi future compat warning a hard error
bjorn3 Dec 6, 2024
49c3aaa
Add test
bjorn3 Jan 9, 2025
1f6517b
Move `std::io::pipe` code into its own file
tbu- Jan 17, 2025
f770f39
Update `std::io::{pipe, PipeReader, PipeWriter}` docs the new location
tbu- Jan 17, 2025
84c8015
Add new target for supporting Neutrino QNX 6.1 with `io-socket` netwo…
flba-eb Nov 28, 2024
efe53dd
Add support for QNX 7.1 with io-sock on x64
flba-eb Nov 29, 2024
62661f2
Move common code to mod nto_qnx
flba-eb Nov 30, 2024
3f045c9
add nto80 x86-64 and aarch64 target
AkhilTThomas Dec 6, 2024
46a0333
Update documentation to include QNX 8.0
flba-eb Dec 10, 2024
0462826
Review nto-qnx.md.
jonathanpallant Jan 13, 2025
2444adf
fix(libtest): Deprecate '--logfile'
epage Dec 13, 2024
8eebbba
ci.py: check the return code in `run-local`
cuviper Jan 23, 2025
492d985
extract principal MIR dump function
lqd Jan 24, 2025
3631c15
use more explicit MIR dumping process
lqd Jan 24, 2025
6baa65e
switch polonius MIR dump to HTML
lqd Jan 24, 2025
82c0168
fix terminator edges comments
lqd Jan 24, 2025
09fb70a
add CFG to polonius MIR dump
lqd Jan 24, 2025
8e74ff4
Rollup merge of #133631 - flba-eb:add_nto_qnx71_iosock_support, r=wor…
matthiaskrgr Jan 26, 2025
9004ed7
Rollup merge of #133951 - bjorn3:wasm_c_abi_lint_hard_error, r=workin…
matthiaskrgr Jan 26, 2025
e31e3cd
Rollup merge of #134283 - epage:logfile, r=Amanieu
matthiaskrgr Jan 26, 2025
e50417e
Rollup merge of #135635 - tbu-:pr_io_pipe, r=joboet
matthiaskrgr Jan 26, 2025
628f7fa
Rollup merge of #135842 - chriskrycho:trpl-2024-edition-more, r=ehuss
matthiaskrgr Jan 26, 2025
780fdb5
Rollup merge of #135953 - cuviper:ci-run-local-fail, r=Kobzol
matthiaskrgr Jan 26, 2025
4374b3f
Rollup merge of #136031 - lqd:polonius-debugger-episode-1, r=compiler…
matthiaskrgr Jan 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 3 additions & 249 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
@@ -310,6 +310,8 @@ pub use self::error::RawOsError;
pub use self::error::SimpleMessage;
#[unstable(feature = "io_const_error", issue = "133448")]
pub use self::error::const_error;
#[unstable(feature = "anonymous_pipe", issue = "127154")]
pub use self::pipe::{PipeReader, PipeWriter, pipe};
#[stable(feature = "is_terminal", since = "1.70.0")]
pub use self::stdio::IsTerminal;
pub(crate) use self::stdio::attempt_print_to_stderr;
@@ -330,14 +332,14 @@ pub use self::{
};
use crate::mem::take;
use crate::ops::{Deref, DerefMut};
use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
use crate::{cmp, fmt, slice, str, sys};

mod buffered;
pub(crate) mod copy;
mod cursor;
mod error;
mod impls;
mod pipe;
pub mod prelude;
mod stdio;
mod util;
@@ -3251,251 +3253,3 @@ impl<B: BufRead> Iterator for Lines<B> {
}
}
}

/// Create anonymous pipe that is close-on-exec and blocking.
///
/// # Behavior
///
/// A pipe is a synchronous, unidirectional data channel between two or more processes, like an
/// interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular:
///
/// * A read on a [`PipeReader`] blocks until the pipe is non-empty.
/// * A write on a [`PipeWriter`] blocks when the pipe is full.
/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`]
/// returns EOF.
/// * [`PipeReader`] can be shared, but only one process will consume the data in the pipe.
///
/// # Capacity
///
/// Pipe capacity is platform dependent. To quote the Linux [man page]:
///
/// > Different implementations have different limits for the pipe capacity. Applications should
/// > not rely on a particular capacity: an application should be designed so that a reading process
/// > consumes data as soon as it is available, so that a writing process does not remain blocked.
///
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
/// # use std::process::Command;
/// # use std::io::{Read, Write};
/// let (ping_rx, mut ping_tx) = std::io::pipe()?;
/// let (mut pong_rx, pong_tx) = std::io::pipe()?;
///
/// // Spawn a process that echoes its input.
/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
///
/// ping_tx.write_all(b"hello")?;
/// // Close to unblock echo_server's reader.
/// drop(ping_tx);
///
/// let mut buf = String::new();
/// // Block until echo_server's writer is closed.
/// pong_rx.read_to_string(&mut buf)?;
/// assert_eq!(&buf, "hello");
///
/// echo_server.wait()?;
/// # Ok(())
/// # }
/// ```
/// [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html
/// [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe
/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html
#[unstable(feature = "anonymous_pipe", issue = "127154")]
#[inline]
pub fn pipe() -> 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.
///
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
/// # use std::fs;
/// # use std::io::Write;
/// # use std::process::Command;
/// const NUM_SLOT: u8 = 2;
/// const NUM_PROC: u8 = 5;
/// const OUTPUT: &str = "work.txt";
///
/// let mut jobs = vec![];
/// let (reader, mut writer) = std::io::pipe()?;
///
/// // Write NUM_SLOT characters the pipe.
/// writer.write_all(&[b'|'; NUM_SLOT as usize])?;
///
/// // Spawn several processes that read a character from the pipe, do some work, then
/// // write back to the pipe. When the pipe is empty, the processes block, so only
/// // NUM_SLOT processes can be working at any given time.
/// for _ in 0..NUM_PROC {
/// jobs.push(
/// Command::new("bash")
/// .args(["-c",
/// &format!(
/// "read -n 1\n\
/// echo -n 'x' >> '{OUTPUT}'\n\
/// echo -n '|'",
/// ),
/// ])
/// .stdin(reader.try_clone()?)
/// .stdout(writer.try_clone()?)
/// .spawn()?,
/// );
/// }
///
/// // Wait for all jobs to finish.
/// for mut job in jobs {
/// job.wait()?;
/// }
///
/// // Check our work and clean up.
/// let xs = fs::read_to_string(OUTPUT)?;
/// fs::remove_file(OUTPUT)?;
/// assert_eq!(xs, "x".repeat(NUM_PROC.into()));
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "anonymous_pipe", issue = "127154")]
pub fn try_clone(&self) -> Result<Self> {
self.0.try_clone().map(Self)
}
}

impl PipeWriter {
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
///
/// # Examples
///
/// ```no_run
/// #![feature(anonymous_pipe)]
/// # #[cfg(miri)] fn main() {}
/// # #[cfg(not(miri))]
/// # fn main() -> std::io::Result<()> {
/// # use std::process::Command;
/// # use std::io::Read;
/// let (mut reader, writer) = std::io::pipe()?;
///
/// // Spawn a process that writes to stdout and stderr.
/// let mut peer = Command::new("bash")
/// .args([
/// "-c",
/// "echo -n foo\n\
/// echo -n bar >&2"
/// ])
/// .stdout(writer.try_clone()?)
/// .stderr(writer)
/// .spawn()?;
///
/// // Read and check the result.
/// let mut msg = String::new();
/// reader.read_to_string(&mut msg)?;
/// assert_eq!(&msg, "foobar");
///
/// peer.wait()?;
/// # Ok(())
/// # }
/// ```
#[unstable(feature = "anonymous_pipe", issue = "127154")]
pub fn try_clone(&self) -> Result<Self> {
self.0.try_clone().map(Self)
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl Read for &PipeReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> 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>) -> Result<usize> {
self.0.read_to_end(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
self.0.read_buf(buf)
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl Read for PipeReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> 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>) -> Result<usize> {
self.0.read_to_end(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
self.0.read_buf(buf)
}
}

#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl Write for &PipeWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> 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 Write for PipeWriter {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
#[inline]
fn flush(&mut self) -> Result<()> {
Ok(())
}

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
self.0.write_vectored(bufs)
}

#[inline]
fn is_write_vectored(&self) -> bool {
self.0.is_write_vectored()
}
}
Loading