2016-12-07 13:21:42 +01:00
|
|
|
#![cfg(unix)]
|
|
|
|
|
|
|
|
|
|
extern crate env_logger;
|
|
|
|
|
extern crate futures;
|
2016-12-08 16:30:18 -08:00
|
|
|
extern crate libc;
|
2016-12-07 13:21:42 +01:00
|
|
|
extern crate mio;
|
2017-10-24 16:30:16 -07:00
|
|
|
extern crate tokio;
|
2017-02-05 17:06:57 -08:00
|
|
|
extern crate tokio_io;
|
2016-12-07 13:21:42 +01:00
|
|
|
|
2016-12-08 16:30:18 -08:00
|
|
|
use std::fs::File;
|
|
|
|
|
use std::io::{self, Write};
|
|
|
|
|
use std::os::unix::io::{AsRawFd, FromRawFd};
|
2016-12-07 13:21:42 +01:00
|
|
|
use std::thread;
|
2016-12-08 16:30:18 -08:00
|
|
|
use std::time::Duration;
|
2016-12-07 13:21:42 +01:00
|
|
|
|
2017-12-11 21:29:18 -06:00
|
|
|
use mio::event::Evented;
|
2017-02-05 17:06:57 -08:00
|
|
|
use mio::unix::{UnixReady, EventedFd};
|
|
|
|
|
use mio::{PollOpt, Ready, Token};
|
2018-03-01 21:50:07 -08:00
|
|
|
use tokio::reactor::{Handle, PollEvented2};
|
2017-02-05 17:06:57 -08:00
|
|
|
use tokio_io::io::read_to_end;
|
2018-02-06 07:26:21 -08:00
|
|
|
use futures::Future;
|
2016-12-07 13:21:42 +01:00
|
|
|
|
|
|
|
|
macro_rules! t {
|
|
|
|
|
($e:expr) => (match $e {
|
|
|
|
|
Ok(e) => e,
|
|
|
|
|
Err(e) => panic!("{} failed with {:?}", stringify!($e), e),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 16:30:18 -08:00
|
|
|
struct MyFile(File);
|
2016-12-07 13:21:42 +01:00
|
|
|
|
2016-12-08 16:30:18 -08:00
|
|
|
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)
|
2016-12-07 13:21:42 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 16:30:18 -08:00
|
|
|
impl io::Read for MyFile {
|
2016-12-07 13:21:42 +01:00
|
|
|
fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
|
|
|
|
|
self.0.read(bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-08 16:30:18 -08:00
|
|
|
impl Evented for MyFile {
|
2016-12-07 13:21:42 +01:00
|
|
|
fn register(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
|
|
|
|
|
-> io::Result<()> {
|
2017-02-05 17:06:57 -08:00
|
|
|
let hup: Ready = UnixReady::hup().into();
|
|
|
|
|
EventedFd(&self.0.as_raw_fd()).register(poll, token, interest | hup, opts)
|
2016-12-07 13:21:42 +01:00
|
|
|
}
|
|
|
|
|
fn reregister(&self, poll: &mio::Poll, token: Token, interest: Ready, opts: PollOpt)
|
|
|
|
|
-> io::Result<()> {
|
2017-02-05 17:06:57 -08:00
|
|
|
let hup: Ready = UnixReady::hup().into();
|
|
|
|
|
EventedFd(&self.0.as_raw_fd()).reregister(poll, token, interest | hup, opts)
|
2016-12-07 13:21:42 +01:00
|
|
|
}
|
|
|
|
|
fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
|
|
|
|
|
EventedFd(&self.0.as_raw_fd()).deregister(poll)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn hup() {
|
2018-08-10 21:37:45 +02:00
|
|
|
drop(env_logger::try_init());
|
2016-12-07 13:21:42 +01:00
|
|
|
|
2017-12-11 21:29:18 -06:00
|
|
|
let handle = Handle::default();
|
2016-12-08 16:30:18 -08:00
|
|
|
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));
|
|
|
|
|
});
|
|
|
|
|
|
2018-03-01 21:50:07 -08:00
|
|
|
let source = PollEvented2::new_with_handle(MyFile::new(read), &handle).unwrap();
|
2016-12-08 16:30:18 -08:00
|
|
|
|
|
|
|
|
let reader = read_to_end(source, Vec::new());
|
2018-02-06 07:26:21 -08:00
|
|
|
let (_, content) = t!(reader.wait());
|
2016-12-08 16:30:18 -08:00
|
|
|
assert_eq!(&b"Hello!\nGood bye!\n"[..], &content[..]);
|
|
|
|
|
t.join().unwrap();
|
|
|
|
|
}
|
2016-12-07 13:21:42 +01:00
|
|
|
}
|