discuss deadlocks in the std::io::pipe() example
This commit is contained in:
parent
c8bda740ea
commit
dcef449e2c
1 changed files with 26 additions and 12 deletions
|
|
@ -38,30 +38,44 @@ use crate::sys_common::{FromInner, IntoInner};
|
|||
/// > 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
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[cfg(miri)] fn main() {}
|
||||
/// # #[cfg(not(miri))]
|
||||
/// # fn main() -> std::io::Result<()> {
|
||||
/// use std::io::{Read, Write, pipe};
|
||||
/// use std::process::Command;
|
||||
/// use std::io::{pipe, Read, Write};
|
||||
/// let (ping_rx, mut ping_tx) = pipe()?;
|
||||
/// let (mut pong_rx, pong_tx) = pipe()?;
|
||||
/// let (ping_reader, mut ping_writer) = pipe()?;
|
||||
/// let (mut pong_reader, pong_writer) = pipe()?;
|
||||
///
|
||||
/// // Spawn a process that echoes its input.
|
||||
/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?;
|
||||
/// // Spawn a child process that echoes its input.
|
||||
/// let mut echo_command = Command::new("cat");
|
||||
/// echo_command.stdin(ping_reader);
|
||||
/// echo_command.stdout(pong_writer);
|
||||
/// let mut echo_child = echo_command.spawn()?;
|
||||
///
|
||||
/// ping_tx.write_all(b"hello")?;
|
||||
/// // Close to unblock echo_server's reader.
|
||||
/// drop(ping_tx);
|
||||
/// // Send input to the child process. Note that because we're writing all the input before we
|
||||
/// // read any output, this could deadlock if the child's input and output pipe buffers both
|
||||
/// // filled up. Those buffers are usually at least a few KB, so "hello" is fine, but for longer
|
||||
/// // inputs we'd need to read and write at the same time, e.g. using threads.
|
||||
/// ping_writer.write_all(b"hello")?;
|
||||
///
|
||||
/// // `cat` exits when it reads EOF from stdin, but that can't happen while any ping writer
|
||||
/// // remains open. We need to drop our ping writer, or read_to_string will deadlock below.
|
||||
/// drop(ping_writer);
|
||||
///
|
||||
/// // The pong reader can't report EOF while any pong writer remains open. Our Command object is
|
||||
/// // holding a pong writer, and again read_to_string will deadlock if we don't drop it.
|
||||
/// drop(echo_command);
|
||||
///
|
||||
/// let mut buf = String::new();
|
||||
/// // Block until echo_server's writer is closed.
|
||||
/// pong_rx.read_to_string(&mut buf)?;
|
||||
/// // Block until `cat` closes its stdout (a pong writer).
|
||||
/// pong_reader.read_to_string(&mut buf)?;
|
||||
/// assert_eq!(&buf, "hello");
|
||||
///
|
||||
/// echo_server.wait()?;
|
||||
/// // At this point we know `cat` has exited, but we still need to wait to clean up the "zombie".
|
||||
/// echo_child.wait()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue