Skip to content

Instantly share code, notes, and snippets.

@se1983
Created March 17, 2024 13:45
Show Gist options
  • Save se1983/331f541a113dc8d5a5ff5e2b41529fc2 to your computer and use it in GitHub Desktop.
Save se1983/331f541a113dc8d5a5ff5e2b41529fc2 to your computer and use it in GitHub Desktop.
epoll in rust using nix
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