Skip to content

fix #480 and add simple test cases for that. #486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#491](https://github.com/nix-rust/nix/pull/491))

### Changed
- `epoll_ctl` now could accept None as argument `event`
when op is `EpollOp::EpollCtlDel`.
([#480](https://github.com/nix-rust/nix/pull/480))
- Removed the `bad` keyword from the `ioctl!` macro
([#478](https://github.com/nix-rust/nix/pull/478))
- Changed `TimeVal` into an opaque Newtype
Expand Down
35 changes: 29 additions & 6 deletions src/sys/epoll.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

bitflags!(
#[repr(C)]
Expand All @@ -23,7 +26,7 @@ bitflags!(
}
);

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
EpollCtlAdd = 1,
Expand All @@ -44,10 +47,14 @@ pub struct EpollEvent {
}

impl EpollEvent {
pub fn new(events: EpollFlags, data: u64) -> EpollEvent {
pub fn new(events: EpollFlags, data: u64) -> Self {
EpollEvent { event: libc::epoll_event { events: events.bits(), u64: data } }
}

pub fn empty() -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give me an example of a use case for this function?

unsafe { mem::zeroed::<EpollEvent>() }
}

pub fn events(&self) -> EpollFlags {
EpollFlags::from_bits(self.event.events).unwrap()
}
Expand All @@ -57,6 +64,16 @@ impl EpollEvent {
}
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
#[inline]
fn into(self) -> &'a mut EpollEvent {
match self {
Some(epoll_event) => epoll_event,
None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
}
}
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
let res = unsafe { libc::epoll_create(1024) };
Expand All @@ -72,10 +89,16 @@ pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
}

#[inline]
pub fn epoll_ctl(epfd: RawFd, op: EpollOp, fd: RawFd, event: &mut EpollEvent) -> Result<()> {
let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };

Errno::result(res).map(drop)
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
where T: Into<&'a mut EpollEvent>
{
let event: &mut EpollEvent = event.into();
if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
Err(Error::Sys(Errno::EINVAL))
} else {
let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
Errno::result(res).map(drop)
}
}

#[inline]
Expand Down
3 changes: 3 additions & 0 deletions test/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ mod test_ioctl;
mod test_wait;
mod test_select;
mod test_uio;

#[cfg(target_os = "linux")]
mod test_epoll;
24 changes: 24 additions & 0 deletions test/sys/test_epoll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use nix::sys::epoll::{EpollCreateFlags, EpollOp, EpollEvent};
use nix::sys::epoll::{EPOLLIN, EPOLLERR};
use nix::sys::epoll::{epoll_create1, epoll_ctl};
use nix::{Error, Errno};

#[test]
pub fn test_epoll_errno() {
let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));

let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
}

#[test]
pub fn test_epoll_ctl() {
let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
let mut event = EpollEvent::new(EPOLLIN | EPOLLERR, 1);
epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap();
epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap();
}