Created
March 17, 2024 13:45
-
-
Save se1983/331f541a113dc8d5a5ff5e2b41529fc2 to your computer and use it in GitHub Desktop.
epoll in rust using nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use clap::Parser; | |
use nix::fcntl::{open, OFlag}; | |
use nix::sys::epoll::{epoll_create, epoll_ctl, epoll_wait, EpollEvent, EpollFlags, EpollOp}; | |
use nix::sys::stat::Mode; | |
use std::collections::HashMap; | |
#[derive(Parser, Debug)] | |
#[clap(author, version, about, long_about = None)] | |
pub struct Cli { | |
#[clap(value_delimiter = ' ', num_args = 1..)] | |
pub fds: Vec<String>, | |
} | |
fn main() { | |
let cli = Cli::parse(); | |
let ep_fd = epoll_create().unwrap(); | |
let mut fd_register = HashMap::new(); | |
let mut events: Vec<EpollEvent> = cli | |
.fds | |
.iter() | |
.map(|fd_name| { | |
let fd = open( | |
fd_name.as_str(), | |
OFlag::O_RDONLY | OFlag::O_NONBLOCK, | |
Mode::all(), | |
) | |
.unwrap_or_else(|_| panic!("Could not open file descriptor {fd_name}")); | |
println!("Opened {fd_name} on {fd}"); | |
fd_register.insert(fd as u64, fd); | |
// Only interested in input events | |
let mut event = EpollEvent::new(EpollFlags::EPOLLIN, fd as u64); | |
epoll_ctl(ep_fd, EpollOp::EpollCtlAdd, fd, &mut event) | |
.expect("Could not register an event."); | |
event | |
}) | |
.collect(); | |
while !fd_register.is_empty() { | |
println!("awaiting epoll.."); | |
// TODO: how to react on EINTR? | |
let ready = epoll_wait(ep_fd, &mut events, -1).unwrap(); | |
println!("Ready: {ready}"); | |
for event in &events { | |
let buf_size = 1024; | |
let mut buf = vec![0u8; buf_size]; | |
// get fd from number: HashMap solution | |
if let Some(fd) = fd_register.get(&event.data()) { | |
println!("fd={fd}; events: {:?}", event.events()); | |
if event.events().contains(EpollFlags::EPOLLIN) { | |
let s = nix::unistd::read(*fd, &mut buf[..]).unwrap_or(0); | |
println!("read {s} bytes: {}", String::from_utf8_lossy(&buf)) | |
} else if event.events().contains(EpollFlags::EPOLLHUP) | |
|| event.events().contains(EpollFlags::EPOLLERR) | |
{ | |
println!("closing fd {fd}"); | |
nix::unistd::close(*fd).unwrap(); | |
fd_register.remove(&event.data()).unwrap(); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment