mio::unix::pipe

Function new

Source
pub fn new() -> Result<(Sender, Receiver)>
Available on Unix and crate feature os-ext and crate feature os-poll only.
Expand description

Create a new non-blocking Unix pipe.

This is a wrapper around Unix’s pipe(2) system call and can be used as inter-process or thread communication channel.

This channel may be created before forking the process and then one end used in each process, e.g. the parent process has the sending end to send command to the child process.

§Events

The Sender can be registered with WRITABLE interest to receive writable events, the Receiver with READABLE interest. Once data is written to the Sender the Receiver will receive an readable event.

In addition to those events, events will also be generated if the other side is dropped. To check if the Sender is dropped you’ll need to check is_read_closed on events for the Receiver, if it returns true the Sender is dropped. On the Sender end check is_write_closed, if it returns true the Receiver was dropped. Also see the second example below.

§Deregistering

Both Sender and Receiver will deregister themselves when dropped, iff the file descriptors are not duplicated (via dup(2)).

§Examples

Simple example that writes data into the sending end and read it from the receiving end.

use std::io::{self, Read, Write};

use mio::{Poll, Events, Interest, Token};
use mio::unix::pipe;

// Unique tokens for the two ends of the channel.
const PIPE_RECV: Token = Token(0);
const PIPE_SEND: Token = Token(1);

// Create our `Poll` instance and the `Events` container.
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(8);

// Create a new pipe.
let (mut sender, mut receiver) = pipe::new()?;

// Register both ends of the channel.
poll.registry().register(&mut receiver, PIPE_RECV, Interest::READABLE)?;
poll.registry().register(&mut sender, PIPE_SEND, Interest::WRITABLE)?;

const MSG: &[u8; 11] = b"Hello world";

loop {
    poll.poll(&mut events, None)?;

    for event in events.iter() {
        match event.token() {
            PIPE_SEND => sender.write(MSG)
                .and_then(|n| if n != MSG.len() {
                        // We'll consider a short write an error in this
                        // example. NOTE: we can't use `write_all` with
                        // non-blocking I/O.
                        Err(io::ErrorKind::WriteZero.into())
                    } else {
                        Ok(())
                    })?,
            PIPE_RECV => {
                let mut buf = [0; 11];
                let n = receiver.read(&mut buf)?;
                println!("received: {:?}", &buf[0..n]);
                assert_eq!(n, MSG.len());
                assert_eq!(&buf, &*MSG);
                return Ok(());
            },
            _ => unreachable!(),
        }
    }
}

Example that receives an event once the Sender is dropped.

// Same setup as in the example above.
let mut poll = Poll::new()?;
let mut events = Events::with_capacity(8);

let (mut sender, mut receiver) = pipe::new()?;

poll.registry().register(&mut receiver, PIPE_RECV, Interest::READABLE)?;
poll.registry().register(&mut sender, PIPE_SEND, Interest::WRITABLE)?;

// Drop the sender.
drop(sender);

poll.poll(&mut events, None)?;

for event in events.iter() {
    match event.token() {
        PIPE_RECV if event.is_read_closed() => {
            // Detected that the sender was dropped.
            println!("Sender dropped!");
            return Ok(());
        },
        _ => unreachable!(),
    }
}