summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio-0.1.22/tests/pipe-hup.rs
blob: eabdec4c80dfd4d0f17d064f294672b501b631ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#![cfg(unix)]

extern crate env_logger;
extern crate futures;
extern crate libc;
extern crate mio;
extern crate tokio;
extern crate tokio_io;

use std::fs::File;
use std::io::{self, Write};
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::thread;
use std::time::Duration;

use futures::Future;
use mio::event::Evented;
use mio::unix::{EventedFd, UnixReady};
use mio::{PollOpt, Ready, Token};
use tokio::reactor::{Handle, PollEvented2};
use tokio_io::io::read_to_end;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
        }
    };
}

struct MyFile(File);

impl MyFile {
    fn new(file: File) -> MyFile {
        unsafe {
            let r = libc::fcntl(file.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            assert!(r != -1, "fcntl error: {}", io::Error::last_os_error());
        }
        MyFile(file)
    }
}

impl io::Read for MyFile {
    fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
        self.0.read(bytes)
    }
}

impl Evented for MyFile {
    fn register(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).register(poll, token, interest | hup, opts)
    }
    fn reregister(
        &self,
        poll: &mio::Poll,
        token: Token,
        interest: Ready,
        opts: PollOpt,
    ) -> io::Result<()> {
        let hup: Ready = UnixReady::hup().into();
        EventedFd(&self.0.as_raw_fd()).reregister(poll, token, interest | hup, opts)
    }
    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        EventedFd(&self.0.as_raw_fd()).deregister(poll)
    }
}

#[test]
fn hup() {
    drop(env_logger::try_init());

    let handle = Handle::default();
    unsafe {
        let mut pipes = [0; 2];
        assert!(
            libc::pipe(pipes.as_mut_ptr()) != -1,
            "pipe error: {}",
            io::Error::last_os_error()
        );
        let read = File::from_raw_fd(pipes[0]);
        let mut write = File::from_raw_fd(pipes[1]);
        let t = thread::spawn(move || {
            write.write_all(b"Hello!\n").unwrap();
            write.write_all(b"Good bye!\n").unwrap();
            thread::sleep(Duration::from_millis(100));
        });

        let source = PollEvented2::new_with_handle(MyFile::new(read), &handle).unwrap();

        let reader = read_to_end(source, Vec::new());
        let (_, content) = t!(reader.wait());
        assert_eq!(&b"Hello!\nGood bye!\n"[..], &content[..]);
        t.join().unwrap();
    }
}