| #![cfg(unix)] |
| |
| extern crate env_logger; |
| extern crate futures; |
| extern crate libc; |
| extern crate mio; |
| extern crate tokio_core; |
| 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 mio::unix::{UnixReady, EventedFd}; |
| use mio::{PollOpt, Ready, Token}; |
| use mio::event::Evented; |
| use tokio_core::reactor::{Core, PollEvented}; |
| 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::init()); |
| |
| let mut l = t!(Core::new()); |
| 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 = PollEvented::new(MyFile::new(read), &l.handle()).unwrap(); |
| |
| let reader = read_to_end(source, Vec::new()); |
| let (_, content) = t!(l.run(reader)); |
| assert_eq!(&b"Hello!\nGood bye!\n"[..], &content[..]); |
| t.join().unwrap(); |
| } |
| } |