about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-12-15 05:08:18 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-12-15 05:08:18 +0000
commit581989d1c6de8ece197b1317e3093203d3203d66 (patch)
tree57e9863e82b35af828fb9ea01e1067f656f8cf26 /library/std/src
parent8f497995ddecbe89efea7d88e8b381da24aac8ed (diff)
parentbb1a90f939cf07a717a36af60b9f58f90ede26c0 (diff)
downloadrust-581989d1c6de8ece197b1317e3093203d3203d66.tar.gz
rust-581989d1c6de8ece197b1317e3093203d3203d66.zip
Merge from rustc
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/path.rs4
-rw-r--r--library/std/src/pipe.rs140
-rw-r--r--library/std/src/sys/pal/hermit/fs.rs6
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs2
-rw-r--r--library/std/src/sys/pal/hermit/os.rs4
6 files changed, 146 insertions, 12 deletions
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 047f5b0c4c5..1cbf51463ea 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -544,6 +544,8 @@ pub use core::u64;
 #[stable(feature = "i128", since = "1.26.0")]
 #[allow(deprecated, deprecated_in_future)]
 pub use core::u128;
+#[unstable(feature = "unsafe_binders", issue = "130516")]
+pub use core::unsafe_binder;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated, deprecated_in_future)]
 pub use core::usize;
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 5b277a982ee..35e920ab344 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2327,7 +2327,9 @@ impl Path {
             // FIXME: Allow Redox prefixes
             self.has_root() || has_redox_scheme(self.as_u8_slice())
         } else {
-            self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some())
+            self.has_root()
+                && (cfg!(any(unix, target_os = "hermit", target_os = "wasi"))
+                    || self.prefix().is_some())
         }
     }
 
diff --git a/library/std/src/pipe.rs b/library/std/src/pipe.rs
index 891032e94a6..06f3fd9fdff 100644
--- a/library/std/src/pipe.rs
+++ b/library/std/src/pipe.rs
@@ -1,20 +1,66 @@
-//! Module for anonymous pipe
+//!  A cross-platform anonymous pipe.
 //!
-//! ```
-//! #![feature(anonymous_pipe)]
+//! This module provides support for anonymous OS pipes, like [pipe] on Linux or [CreatePipe] on
+//! Windows.
+//!
+//! # 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<()> {
-//! let (reader, writer) = std::pipe::pipe()?;
+//! # use std::process::Command;
+//! # use std::io::{Read, Write};
+//! let (ping_rx, mut ping_tx) = std::pipe::pipe()?;
+//! let (mut pong_rx, pong_tx) = std::pipe::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
 use crate::io;
 use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner};
 
 /// Create anonymous pipe that is close-on-exec and blocking.
+///
+/// # Examples
+///
+/// See the [module-level](crate::pipe) documentation for examples.
 #[unstable(feature = "anonymous_pipe", issue = "127154")]
 #[inline]
 pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
@@ -33,6 +79,58 @@ 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::pipe::pipe()?;
+    ///
+    /// // Write NUM_SLOT characters the 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) -> io::Result<Self> {
         self.0.try_clone().map(Self)
@@ -41,6 +139,38 @@ impl PipeReader {
 
 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::pipe::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) -> io::Result<Self> {
         self.0.try_clone().map(Self)
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index 11862a07608..88fc4068719 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -3,7 +3,7 @@ use super::hermit_abi::{
     self, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY,
     O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, dirent64, stat as stat_struct,
 };
-use crate::ffi::{CStr, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString, c_char};
 use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
 use crate::os::hermit::ffi::OsStringExt;
 use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
@@ -204,7 +204,7 @@ impl Iterator for ReadDir {
                 // the size of dirent64. The file name is always a C string and terminated by `\0`.
                 // Consequently, we are able to ignore the last byte.
                 let name_bytes =
-                    unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() };
+                    unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const c_char).to_bytes() };
                 let entry = DirEntry {
                     root: self.inner.root.clone(),
                     ino: dir.d_ino,
@@ -445,7 +445,7 @@ impl DirBuilder {
 
     pub fn mkdir(&self, path: &Path) -> io::Result<()> {
         run_path_with_cstr(path, &|path| {
-            cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ())
+            cvt(unsafe { hermit_abi::mkdir(path.as_ptr().cast(), self.mode.into()) }).map(|_| ())
         })
     }
 
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index f03fca60344..d833c9d632c 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -85,7 +85,7 @@ pub unsafe extern "C" fn runtime_entry(
     }
 
     // initialize environment
-    os::init_environment(env as *const *const i8);
+    os::init_environment(env);
 
     let result = unsafe { main(argc as isize, argv) };
 
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index f8ea80afa43..791cdb1e57e 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -3,7 +3,7 @@ use core::slice::memchr;
 use super::hermit_abi;
 use crate::collections::HashMap;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString, c_char};
 use crate::marker::PhantomData;
 use crate::os::hermit::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
@@ -70,7 +70,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
 
-pub fn init_environment(env: *const *const i8) {
+pub fn init_environment(env: *const *const c_char) {
     let mut guard = ENV.lock().unwrap();
     let map = guard.insert(HashMap::new());