From a17bb7b26b82dfb3384f0187cad49c86db4c7b79 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Tue, 16 Aug 2016 03:38:57 -0600 Subject: [PATCH 1/7] Define kqueue-related stuff in terms of libc Change 11aa1f34243d5bbb7d6327a6607bd9d2530f3954 to libc added kqueue-related definitions. They are more accurate and more complete than nix's own definitions. Use them where possible. Also, rationalize Nix's definitions so its public API will be as similar as possible across all OSes. --- src/sys/event.rs | 475 ++++++++++++++++++----------------------- test/sys/mod.rs | 1 + test/sys/test_event.rs | 30 +++ 3 files changed, 240 insertions(+), 266 deletions(-) create mode 100644 test/sys/test_event.rs diff --git a/src/sys/event.rs b/src/sys/event.rs index 0e94475e18..eb179f0589 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -3,278 +3,237 @@ use {Errno, Result}; #[cfg(not(target_os = "netbsd"))] -use libc::{timespec, time_t, c_int, c_long, uintptr_t}; +use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t}; #[cfg(target_os = "netbsd")] -use libc::{timespec, time_t, c_long, uintptr_t, size_t}; +use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t}; +use libc; use std::os::unix::io::RawFd; use std::ptr; -pub use self::ffi::kevent as KEvent; - -mod ffi { - pub use libc::{c_int, c_void, uintptr_t, intptr_t, timespec, size_t, int64_t}; - use super::{EventFilter, EventFlag, FilterFlag}; - - #[cfg(not(target_os = "netbsd"))] - #[derive(Clone, Copy)] - #[repr(C)] - pub struct kevent { - pub ident: uintptr_t, // 8 - pub filter: EventFilter, // 2 - pub flags: EventFlag, // 2 - pub fflags: FilterFlag, // 4 - pub data: intptr_t, // 8 - pub udata: usize // 8 - } - - #[cfg(target_os = "netbsd")] - #[derive(Clone, Copy)] - #[repr(C)] - pub struct kevent { - pub ident: uintptr_t, - pub filter: EventFilter, - pub flags: EventFlag, - pub fflags: FilterFlag, - pub data: int64_t, - pub udata: intptr_t - } - - // Bug in rustc, cannot determine that kevent is #[repr(C)] - #[allow(improper_ctypes)] - extern { - pub fn kqueue() -> c_int; - - #[cfg(not(target_os = "netbsd"))] - pub fn kevent( - kq: c_int, - changelist: *const kevent, - nchanges: c_int, - eventlist: *mut kevent, - nevents: c_int, - timeout: *const timespec) -> c_int; - - #[cfg(target_os = "netbsd")] - pub fn kevent( - kq: c_int, - changelist: *const kevent, - nchanges: size_t, - eventlist: *mut kevent, - nevents: size_t, - timeout: *const timespec) -> c_int; - } +// Redefine kevent in terms of programmer-friendly enums and bitfields. +#[derive(Clone, Copy)] +#[repr(C)] +pub struct KEvent { + pub ident: uintptr_t, + pub filter: EventFilter, + pub flags: EventFlag, + pub fflags: FilterFlag, + pub data: intptr_t, + // libc defines udata as a pointer on most OSes. But it's really + // more like an arbitrary tag + pub udata: uintptr_t } -#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] +#[cfg(not(target_os = "netbsd"))] #[repr(i16)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum EventFilter { - EVFILT_READ = -1, - EVFILT_WRITE = -2, - EVFILT_AIO = -3, - EVFILT_VNODE = -4, - EVFILT_PROC = -5, - EVFILT_SIGNAL = -6, - EVFILT_TIMER = -7, - EVFILT_MACHPORT = -8, - EVFILT_FS = -9, - EVFILT_USER = -10, - // -11: unused - EVFILT_VM = -12, - EVFILT_SYSCOUNT = 13 -} - -#[cfg(target_os = "dragonfly")] -#[repr(i16)] // u_short -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum EventFilter { - EVFILT_READ = -1, - EVFILT_WRITE = -2, - EVFILT_AIO = -3, - EVFILT_VNODE = -4, - EVFILT_PROC = -5, - EVFILT_SIGNAL = -6, - EVFILT_TIMER = -7, - EVFILT_EXCEPT = -8, - EVFILT_USER = -9, + EVFILT_AIO = libc::EVFILT_AIO, + #[cfg(target_os = "dragonfly")] + EVFILT_EXCEPT = libc::EVFILT_EXCEPT, + #[cfg(any(target_os = "macos", + target_os = "dragonfly", + target_os = "freebsd"))] + EVFILT_FS = libc::EVFILT_FS, + #[cfg(target_os = "freebsd")] + EVFILT_LIO = libc::EVFILT_LIO, + #[cfg(target_os = "macos")] + EVFILT_MACHPORT = libc::EVFILT_MACHPORT, + EVFILT_PROC = libc::EVFILT_PROC, + #[cfg(target_os = "freebsd")] + EVFILT_PROCDESC = libc::EVFILT_PROCDESC, + EVFILT_READ = libc::EVFILT_READ, + #[cfg(target_os = "freebsd")] + EVFILT_SENDFILE = libc::EVFILT_SENDFILE, + EVFILT_SIGNAL = libc::EVFILT_SIGNAL, + EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT, + EVFILT_TIMER = libc::EVFILT_TIMER, + #[cfg(any(target_os = "macos", + target_os = "dragonfly", + target_os = "freebsd"))] + EVFILT_USER = libc::EVFILT_USER, + #[cfg(target_os = "macos")] + EVFILT_VM = libc::EVFILT_VM, + EVFILT_VNODE = libc::EVFILT_VNODE, + EVFILT_WRITE = libc::EVFILT_WRITE, } #[cfg(target_os = "netbsd")] #[repr(u32)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum EventFilter { - EVFILT_READ = 0, - EVFILT_WRITE = 1, - EVFILT_AIO = 2, - EVFILT_VNODE = 3, - EVFILT_PROC = 4, - EVFILT_SIGNAL = 5, - EVFILT_TIMER = 6, - EVFILT_SYSCOUNT = 7 + EVFILT_READ = libc::EVFILT_READ, + EVFILT_WRITE = libc::EVFILT_WRITE, + EVFILT_AIO = libc::EVFILT_AIO, + EVFILT_VNODE = libc::EVFILT_VNODE, + EVFILT_PROC = libc::EVFILT_PROC, + EVFILT_SIGNAL = libc::EVFILT_SIGNAL, + EVFILT_TIMER = libc::EVFILT_TIMER, + EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT, } -#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] +#[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] bitflags!( flags EventFlag: u16 { - const EV_ADD = 0x0001, - const EV_DELETE = 0x0002, - const EV_ENABLE = 0x0004, - const EV_DISABLE = 0x0008, - const EV_RECEIPT = 0x0040, - const EV_ONESHOT = 0x0010, - const EV_CLEAR = 0x0020, - const EV_DISPATCH = 0x0080, - const EV_SYSFLAGS = 0xF000, - const EV_FLAG0 = 0x1000, - const EV_FLAG1 = 0x2000, - const EV_EOF = 0x8000, - const EV_ERROR = 0x4000 + const EV_ADD = libc::EV_ADD, + const EV_CLEAR = libc::EV_CLEAR, + const EV_DELETE = libc::EV_DELETE, + const EV_DISABLE = libc::EV_DISABLE, + const EV_DISPATCH = libc::EV_DISPATCH, + #[cfg(target_os = "freebsd")] + const EV_DROP = libc::EV_DROP, + const EV_ENABLE = libc::EV_ENABLE, + const EV_EOF = libc::EV_EOF, + const EV_ERROR = libc::EV_ERROR, + #[cfg(target_os = "macos")] + const EV_FLAG0 = libc::EV_FLAG0, + const EV_FLAG1 = libc::EV_FLAG1, + #[cfg(target_os = "freebsd")] + const EV_FLAG2 = libc::EV_FLAG2, + #[cfg(target_os = "freebsd")] + const EV_FORCEONESHOT = libc::EV_FORCEONESHOT, + #[cfg(target_os = "dragonfly")] + const EV_NODATA = libc::EV_NODATA, + const EV_ONESHOT = libc::EV_ONESHOT, + #[cfg(target_os = "macos")] + const EV_OOBAND = libc::EV_OOBAND, + #[cfg(target_os = "macos")] + const EV_POLL = libc::EV_POLL, + const EV_RECEIPT = libc::EV_RECEIPT, + const EV_SYSFLAGS = libc::EV_SYSFLAGS, } ); -#[cfg(target_os = "dragonfly")] -bitflags!( - flags EventFlag: u16 { - const EV_ADD = 0x0001, - const EV_DELETE = 0x0002, - const EV_ENABLE = 0x0004, - const EV_DISABLE = 0x0008, - const EV_RECEIPT = 0x0040, - const EV_ONESHOT = 0x0010, - const EV_CLEAR = 0x0020, - const EV_SYSFLAGS = 0xF000, - const EV_NODATA = 0x1000, - const EV_FLAG1 = 0x2000, - const EV_EOF = 0x8000, - const EV_ERROR = 0x4000 - } -); - -#[cfg(target_os = "netbsd")] +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] bitflags!( flags EventFlag: u32 { - const EV_ADD = 0x0001, - const EV_DELETE = 0x0002, - const EV_ENABLE = 0x0004, - const EV_DISABLE = 0x0008, - const EV_ONESHOT = 0x0010, - const EV_CLEAR = 0x0020, - const EV_SYSFLAGS = 0xF000, - const EV_NODATA = 0x1000, - const EV_FLAG1 = 0x2000, - const EV_EOF = 0x8000, - const EV_ERROR = 0x4000 - } -); - -#[cfg(not(any(target_os = "dragonfly", target_os="netbsd")))] -bitflags!( - flags FilterFlag: u32 { - const NOTE_TRIGGER = 0x01000000, - const NOTE_FFNOP = 0x00000000, - const NOTE_FFAND = 0x40000000, - const NOTE_FFOR = 0x80000000, - const NOTE_FFCOPY = 0xc0000000, - const NOTE_FFCTRLMASK = 0xc0000000, - const NOTE_FFLAGSMASK = 0x00ffffff, - const NOTE_LOWAT = 0x00000001, - const NOTE_DELETE = 0x00000001, - const NOTE_WRITE = 0x00000002, - const NOTE_EXTEND = 0x00000004, - const NOTE_ATTRIB = 0x00000008, - const NOTE_LINK = 0x00000010, - const NOTE_RENAME = 0x00000020, - const NOTE_REVOKE = 0x00000040, - const NOTE_NONE = 0x00000080, - const NOTE_EXIT = 0x80000000, - const NOTE_FORK = 0x40000000, - const NOTE_EXEC = 0x20000000, - const NOTE_REAP = 0x10000000, - const NOTE_SIGNAL = 0x08000000, - const NOTE_EXITSTATUS = 0x04000000, - const NOTE_RESOURCEEND = 0x02000000, - const NOTE_APPACTIVE = 0x00800000, - const NOTE_APPBACKGROUND = 0x00400000, - const NOTE_APPNONUI = 0x00200000, - const NOTE_APPINACTIVE = 0x00100000, - const NOTE_APPALLSTATES = 0x00f00000, - const NOTE_PDATAMASK = 0x000fffff, - const NOTE_PCTRLMASK = 0xfff00000, - const NOTE_EXIT_REPARENTED = 0x00080000, - const NOTE_VM_PRESSURE = 0x80000000, - const NOTE_VM_PRESSURE_TERMINATE = 0x40000000, - const NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000, - const NOTE_VM_ERROR = 0x10000000, - const NOTE_SECONDS = 0x00000001, - const NOTE_USECONDS = 0x00000002, - const NOTE_NSECONDS = 0x00000004, - const NOTE_ABSOLUTE = 0x00000008, - const NOTE_TRACK = 0x00000001, - const NOTE_TRACKERR = 0x00000002, - const NOTE_CHILD = 0x00000004 - } -); - -#[cfg(target_os = "dragonfly")] -bitflags!( - flags FilterFlag: u32 { - const NOTE_TRIGGER = 0x01000000, - const NOTE_FFNOP = 0x00000000, - const NOTE_FFAND = 0x40000000, - const NOTE_FFOR = 0x80000000, - const NOTE_FFCOPY = 0xc0000000, - const NOTE_FFCTRLMASK = 0xc0000000, - const NOTE_FFLAGSMASK = 0x00ffffff, - const NOTE_LOWAT = 0x00000001, - const NOTE_DELETE = 0x00000001, - const NOTE_WRITE = 0x00000002, - const NOTE_EXTEND = 0x00000004, - const NOTE_ATTRIB = 0x00000008, - const NOTE_LINK = 0x00000010, - const NOTE_RENAME = 0x00000020, - const NOTE_REVOKE = 0x00000040, - const NOTE_EXIT = 0x80000000, - const NOTE_FORK = 0x40000000, - const NOTE_EXEC = 0x20000000, - const NOTE_SIGNAL = 0x08000000, - const NOTE_PDATAMASK = 0x000fffff, - const NOTE_PCTRLMASK = 0xf0000000, // NOTE: FreeBSD uses 0xfff00000, - const NOTE_TRACK = 0x00000001, - const NOTE_TRACKERR = 0x00000002, - const NOTE_CHILD = 0x00000004 + const EV_ADD = libc::EV_ADD, + const EV_DELETE = libc::EV_DELETE, + const EV_ENABLE = libc::EV_ENABLE, + const EV_DISABLE = libc::EV_DISABLE, + const EV_ONESHOT = libc::EV_ONESHOT, + const EV_CLEAR = libc::EV_CLEAR, + #[cfg(target_os = "openbsd")] + const EV_FLAG1 = libc::EV_FLAG1, + #[cfg(target_os = "netbsd")] + const EV_RECEIPT = libc::EV_RECEIPT, + const EV_DISPATCH = libc::EV_DISPATCH, + const EV_SYSFLAGS = libc::EV_SYSFLAGS, + const EV_FLAG1 = libc::EV_FLAG1, + const EV_EOF = libc::EV_EOF, + const EV_ERROR = libc::EV_ERROR, } ); -#[cfg(target_os = "netbsd")] bitflags!( flags FilterFlag: u32 { - const NOTE_LOWAT = 0x00000001, - const NOTE_DELETE = 0x00000001, - const NOTE_WRITE = 0x00000002, - const NOTE_EXTEND = 0x00000004, - const NOTE_ATTRIB = 0x00000008, - const NOTE_LINK = 0x00000010, - const NOTE_RENAME = 0x00000020, - const NOTE_REVOKE = 0x00000040, - const NOTE_EXIT = 0x80000000, - const NOTE_FORK = 0x40000000, - const NOTE_EXEC = 0x20000000, - const NOTE_SIGNAL = 0x08000000, - const NOTE_PDATAMASK = 0x000fffff, - const NOTE_PCTRLMASK = 0xf0000000, // NOTE: FreeBSD uses 0xfff00000, - const NOTE_TRACK = 0x00000001, - const NOTE_TRACKERR = 0x00000002, - const NOTE_CHILD = 0x00000004 + #[cfg(target_os = "macos")] + const NOTE_ABSOLUTE = libc::NOTE_ABSOLUTE, + #[cfg(target_os = "macos")] + const NOTE_APPACTIVE = libc::NOTE_APPACTIVE, + #[cfg(target_os = "macos")] + const NOTE_APPALLSTATES = libc::NOTE_APPALLSTATES, + #[cfg(target_os = "macos")] + const NOTE_APPBACKGROUND = libc::NOTE_APPBACKGROUND, + #[cfg(target_os = "macos")] + const NOTE_APPINACTIVE = libc::NOTE_APPINACTIVE, + #[cfg(target_os = "macos")] + const NOTE_APPNONUI = libc::NOTE_APPNONUI, + const NOTE_ATTRIB = libc::NOTE_ATTRIB, + const NOTE_CHILD = libc::NOTE_CHILD, + #[cfg(target_os = "freebsd")] + const NOTE_CLOSE = libc::NOTE_CLOSE, + #[cfg(target_os = "freebsd")] + const NOTE_CLOSE_WRITE = libc::NOTE_CLOSE_WRITE, + const NOTE_DELETE = libc::NOTE_DELETE, + #[cfg(target_os = "openbsd")] + const NOTE_EOF = libc::NOTE_EOF, + const NOTE_EXEC = libc::NOTE_EXEC, + const NOTE_EXIT = libc::NOTE_EXIT, + #[cfg(target_os = "macos")] + const NOTE_EXIT_REPARENTED = libc::NOTE_EXIT_REPARENTED, + #[cfg(target_os = "macos")] + const NOTE_EXITSTATUS = libc::NOTE_EXITSTATUS, + const NOTE_EXTEND = libc::NOTE_EXTEND, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFAND = libc::NOTE_FFAND, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFCOPY = libc::NOTE_FFCOPY, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFCTRLMASK = libc::NOTE_FFCTRLMASK, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFLAGSMASK = libc::NOTE_FFLAGSMASK, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFNOP = libc::NOTE_FFNOP, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_FFOR = libc::NOTE_FFOR, + #[cfg(target_os = "freebsd")] + const NOTE_FILE_POLL = libc::NOTE_FILE_POLL, + const NOTE_FORK = libc::NOTE_FORK, + const NOTE_LINK = libc::NOTE_LINK, + const NOTE_LOWAT = libc::NOTE_LOWAT, + #[cfg(target_os = "freebsd")] + const NOTE_MSECONDS = libc::NOTE_MSECONDS, + #[cfg(target_os = "macos")] + const NOTE_NONE = libc::NOTE_NONE, + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + const NOTE_NSECONDS = libc::NOTE_NSECONDS, + #[cfg(target_os = "dragonfly")] + const NOTE_OOB = libc::NOTE_OOB, + #[cfg(target_os = "freebsd")] + const NOTE_OPEN = libc::NOTE_OPEN, + const NOTE_PCTRLMASK = libc::NOTE_PCTRLMASK, + const NOTE_PDATAMASK = libc::NOTE_PDATAMASK, + #[cfg(target_os = "freebsd")] + const NOTE_READ = libc::NOTE_READ, + #[cfg(target_os = "macos")] + const NOTE_REAP = libc::NOTE_REAP, + const NOTE_RENAME = libc::NOTE_RENAME, + #[cfg(target_os = "macos")] + const NOTE_RESOURCEEND = libc::NOTE_RESOURCEEND, + const NOTE_REVOKE = libc::NOTE_REVOKE, + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + const NOTE_SECONDS = libc::NOTE_SECONDS, + #[cfg(target_os = "macos")] + const NOTE_SIGNAL = libc::NOTE_SIGNAL, + const NOTE_TRACK = libc::NOTE_TRACK, + const NOTE_TRACKERR = libc::NOTE_TRACKERR, + #[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] + const NOTE_TRIGGER = libc::NOTE_TRIGGER, + #[cfg(target_os = "openbsd")] + const NOTE_TRUNCATE = libc::NOTE_TRUNCATE, + #[cfg(any(target_os = "macos", target_os = "freebsd"))] + const NOTE_USECONDS = libc::NOTE_USECONDS, + #[cfg(target_os = "macos")] + const NOTE_VM_ERROR = libc::NOTE_VM_ERROR, + #[cfg(target_os = "macos")] + const NOTE_VM_PRESSURE = libc::NOTE_VM_PRESSURE, + #[cfg(target_os = "macos")] + const NOTE_VM_PRESSURE_SUDDEN_TERMINATE = libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE, + #[cfg(target_os = "macos")] + const NOTE_VM_PRESSURE_TERMINATE = libc::NOTE_VM_PRESSURE_TERMINATE, + const NOTE_WRITE = libc::NOTE_WRITE, } ); -#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] -pub const EV_POLL: EventFlag = EV_FLAG0; - -#[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] -pub const EV_OOBAND: EventFlag = EV_FLAG1; - pub fn kqueue() -> Result { - let res = unsafe { ffi::kqueue() }; + let res = unsafe { libc::kqueue() }; Errno::result(res) } @@ -293,18 +252,20 @@ pub fn kevent(kq: RawFd, kevent_ts(kq, changelist, eventlist, Some(timeout)) } -#[cfg(not(target_os = "netbsd"))] +#[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] pub fn kevent_ts(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], timeout_opt: Option) -> Result { let res = unsafe { - ffi::kevent( + libc::kevent( kq, - changelist.as_ptr(), + changelist.as_ptr() as *const libc::kevent, changelist.len() as c_int, - eventlist.as_mut_ptr(), + eventlist.as_mut_ptr() as *mut libc::kevent, eventlist.len() as c_int, if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()}) }; @@ -312,18 +273,18 @@ pub fn kevent_ts(kq: RawFd, Errno::result(res).map(|r| r as usize) } -#[cfg(target_os = "netbsd")] +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] pub fn kevent_ts(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], timeout_opt: Option) -> Result { let res = unsafe { - ffi::kevent( + libc::kevent( kq, - changelist.as_ptr(), + changelist.as_ptr() as *const libc::kevent, changelist.len() as size_t, - eventlist.as_mut_ptr(), + eventlist.as_mut_ptr() as *mut libc::kevent, eventlist.len() as size_t, if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()}) }; @@ -331,31 +292,13 @@ pub fn kevent_ts(kq: RawFd, Errno::result(res).map(|r| r as usize) } -#[cfg(not(target_os = "netbsd"))] -#[inline] -pub fn ev_set(ev: &mut KEvent, - ident: usize, - filter: EventFilter, - flags: EventFlag, - fflags: FilterFlag, - udata: usize) { - - ev.ident = ident as uintptr_t; - ev.filter = filter; - ev.flags = flags; - ev.fflags = fflags; - ev.data = 0; - ev.udata = udata; -} - -#[cfg(target_os = "netbsd")] #[inline] pub fn ev_set(ev: &mut KEvent, ident: usize, filter: EventFilter, flags: EventFlag, fflags: FilterFlag, - udata: isize) { + udata: uintptr_t) { ev.ident = ident as uintptr_t; ev.filter = filter; diff --git a/test/sys/mod.rs b/test/sys/mod.rs index a5f3351df3..ba6d46e2a7 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -1,3 +1,4 @@ +mod test_event; mod test_socket; mod test_sockopt; mod test_termios; diff --git a/test/sys/test_event.rs b/test/sys/test_event.rs new file mode 100644 index 0000000000..f46e7c42e2 --- /dev/null +++ b/test/sys/test_event.rs @@ -0,0 +1,30 @@ +use nix::sys::event; +use libc; +use std::mem::{size_of, size_of_val}; +use std::ptr; + +#[test] +/// Check that nix::event::KEvent has the same layout as libc::kevent +/// This would be easier with offsetof operators. +/// https://github.com/rust-lang/rfcs/issues/1144 +fn test_struct_kevent() { + let expected = libc::kevent{ident: 0, + filter: 0, + flags: 0, + fflags: 0, + data: 0, + udata: ptr::null_mut()}; + let actual = event::KEvent{ ident: 0, + filter: event::EventFilter::EVFILT_READ, + flags: event::EventFlag::empty(), + fflags: event::FilterFlag::empty(), + data: 0, + udata: 0}; + assert!(size_of::() == size_of::()); + assert!(size_of_val(&expected.ident) == size_of_val(&actual.ident)); + assert!(size_of_val(&expected.filter) == size_of_val(&actual.filter)); + assert!(size_of_val(&expected.flags) == size_of_val(&actual.flags)); + assert!(size_of_val(&expected.fflags) == size_of_val(&actual.fflags)); + assert!(size_of_val(&expected.data) == size_of_val(&actual.data)); + assert!(size_of_val(&expected.udata) == size_of_val(&actual.udata)); +} From cf5fccf100fb0af92d87995dac383f649a6b9c98 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 8 Sep 2016 19:58:09 -0600 Subject: [PATCH 2/7] Reconcile with libc changes The final version of libc's PR #379 removed a few definitions, and fixed OpenBSD's definition of fn kevent. --- src/sys/event.rs | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/sys/event.rs b/src/sys/event.rs index eb179f0589..c8c197b299 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -40,13 +40,8 @@ pub enum EventFilter { #[cfg(target_os = "macos")] EVFILT_MACHPORT = libc::EVFILT_MACHPORT, EVFILT_PROC = libc::EVFILT_PROC, - #[cfg(target_os = "freebsd")] - EVFILT_PROCDESC = libc::EVFILT_PROCDESC, EVFILT_READ = libc::EVFILT_READ, - #[cfg(target_os = "freebsd")] - EVFILT_SENDFILE = libc::EVFILT_SENDFILE, EVFILT_SIGNAL = libc::EVFILT_SIGNAL, - EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT, EVFILT_TIMER = libc::EVFILT_TIMER, #[cfg(any(target_os = "macos", target_os = "dragonfly", @@ -69,7 +64,6 @@ pub enum EventFilter { EVFILT_PROC = libc::EVFILT_PROC, EVFILT_SIGNAL = libc::EVFILT_SIGNAL, EVFILT_TIMER = libc::EVFILT_TIMER, - EVFILT_SYSCOUNT = libc::EVFILT_SYSCOUNT, } #[cfg(any(target_os = "macos", @@ -90,10 +84,6 @@ bitflags!( #[cfg(target_os = "macos")] const EV_FLAG0 = libc::EV_FLAG0, const EV_FLAG1 = libc::EV_FLAG1, - #[cfg(target_os = "freebsd")] - const EV_FLAG2 = libc::EV_FLAG2, - #[cfg(target_os = "freebsd")] - const EV_FORCEONESHOT = libc::EV_FORCEONESHOT, #[cfg(target_os = "dragonfly")] const EV_NODATA = libc::EV_NODATA, const EV_ONESHOT = libc::EV_ONESHOT, @@ -143,10 +133,6 @@ bitflags!( const NOTE_APPNONUI = libc::NOTE_APPNONUI, const NOTE_ATTRIB = libc::NOTE_ATTRIB, const NOTE_CHILD = libc::NOTE_CHILD, - #[cfg(target_os = "freebsd")] - const NOTE_CLOSE = libc::NOTE_CLOSE, - #[cfg(target_os = "freebsd")] - const NOTE_CLOSE_WRITE = libc::NOTE_CLOSE_WRITE, const NOTE_DELETE = libc::NOTE_DELETE, #[cfg(target_os = "openbsd")] const NOTE_EOF = libc::NOTE_EOF, @@ -181,8 +167,6 @@ bitflags!( target_os = "freebsd", target_os = "dragonfly"))] const NOTE_FFOR = libc::NOTE_FFOR, - #[cfg(target_os = "freebsd")] - const NOTE_FILE_POLL = libc::NOTE_FILE_POLL, const NOTE_FORK = libc::NOTE_FORK, const NOTE_LINK = libc::NOTE_LINK, const NOTE_LOWAT = libc::NOTE_LOWAT, @@ -194,12 +178,8 @@ bitflags!( const NOTE_NSECONDS = libc::NOTE_NSECONDS, #[cfg(target_os = "dragonfly")] const NOTE_OOB = libc::NOTE_OOB, - #[cfg(target_os = "freebsd")] - const NOTE_OPEN = libc::NOTE_OPEN, const NOTE_PCTRLMASK = libc::NOTE_PCTRLMASK, const NOTE_PDATAMASK = libc::NOTE_PDATAMASK, - #[cfg(target_os = "freebsd")] - const NOTE_READ = libc::NOTE_READ, #[cfg(target_os = "macos")] const NOTE_REAP = libc::NOTE_REAP, const NOTE_RENAME = libc::NOTE_RENAME, @@ -254,7 +234,8 @@ pub fn kevent(kq: RawFd, #[cfg(any(target_os = "macos", target_os = "freebsd", - target_os = "dragonfly"))] + target_os = "dragonfly", + target_os = "openbsd"))] pub fn kevent_ts(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], @@ -273,7 +254,7 @@ pub fn kevent_ts(kq: RawFd, Errno::result(res).map(|r| r as usize) } -#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] +#[cfg(target_os = "netbsd")] pub fn kevent_ts(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], From 9613b10b8dec0f1fb7e08c99d5f2191305902b3a Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 8 Sep 2016 20:04:44 -0600 Subject: [PATCH 3/7] Disable sys/event tests on Linux --- test/sys/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/sys/mod.rs b/test/sys/mod.rs index ba6d46e2a7..39455845d1 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -1,3 +1,5 @@ +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", + target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))] mod test_event; mod test_socket; mod test_sockopt; From a62b2a3d7107f6684798226fedecb039b229d09f Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 8 Sep 2016 20:31:34 -0600 Subject: [PATCH 4/7] Remove macos NOTE_ definitions that aren't in libc --- src/sys/event.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/sys/event.rs b/src/sys/event.rs index c8c197b299..86970c981f 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -121,16 +121,6 @@ bitflags!( flags FilterFlag: u32 { #[cfg(target_os = "macos")] const NOTE_ABSOLUTE = libc::NOTE_ABSOLUTE, - #[cfg(target_os = "macos")] - const NOTE_APPACTIVE = libc::NOTE_APPACTIVE, - #[cfg(target_os = "macos")] - const NOTE_APPALLSTATES = libc::NOTE_APPALLSTATES, - #[cfg(target_os = "macos")] - const NOTE_APPBACKGROUND = libc::NOTE_APPBACKGROUND, - #[cfg(target_os = "macos")] - const NOTE_APPINACTIVE = libc::NOTE_APPINACTIVE, - #[cfg(target_os = "macos")] - const NOTE_APPNONUI = libc::NOTE_APPNONUI, const NOTE_ATTRIB = libc::NOTE_ATTRIB, const NOTE_CHILD = libc::NOTE_CHILD, const NOTE_DELETE = libc::NOTE_DELETE, @@ -183,8 +173,6 @@ bitflags!( #[cfg(target_os = "macos")] const NOTE_REAP = libc::NOTE_REAP, const NOTE_RENAME = libc::NOTE_RENAME, - #[cfg(target_os = "macos")] - const NOTE_RESOURCEEND = libc::NOTE_RESOURCEEND, const NOTE_REVOKE = libc::NOTE_REVOKE, #[cfg(any(target_os = "macos", target_os = "freebsd"))] const NOTE_SECONDS = libc::NOTE_SECONDS, From 2c97154d3e8c466a9fbd62cd4c0d437f5adf87ce Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 18 Sep 2016 22:41:54 -0600 Subject: [PATCH 5/7] struct KEvent should wrap an inner libc::kevent structure --- src/sys/event.rs | 126 ++++++++++++++++++++++++++++++----------- test/sys/mod.rs | 3 - test/sys/test_event.rs | 30 ---------- 3 files changed, 92 insertions(+), 67 deletions(-) delete mode 100644 test/sys/test_event.rs diff --git a/src/sys/event.rs b/src/sys/event.rs index 86970c981f..28d8249528 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -9,21 +9,23 @@ use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t}; use libc; use std::os::unix::io::RawFd; use std::ptr; +use std::mem; // Redefine kevent in terms of programmer-friendly enums and bitfields. #[derive(Clone, Copy)] #[repr(C)] pub struct KEvent { - pub ident: uintptr_t, - pub filter: EventFilter, - pub flags: EventFlag, - pub fflags: FilterFlag, - pub data: intptr_t, - // libc defines udata as a pointer on most OSes. But it's really - // more like an arbitrary tag - pub udata: uintptr_t + kevent: libc::kevent, } +#[cfg(any(target_os = "openbsd", target_os = "freebsd", + target_os = "dragonfly", target_os = "macos"))] +type type_of_udata = *mut ::c_void; +#[cfg(any(target_os = "netbsd"))] +type type_of_udata = intptr_t; + +#[cfg(not(target_os = "netbsd"))] +type type_of_event_filter = i16; #[cfg(not(target_os = "netbsd"))] #[repr(i16)] #[derive(Clone, Copy, Debug, PartialEq)] @@ -53,6 +55,8 @@ pub enum EventFilter { EVFILT_WRITE = libc::EVFILT_WRITE, } +#[cfg(target_os = "netbsd")] +type type_of_event_filter = i32; #[cfg(target_os = "netbsd")] #[repr(u32)] #[derive(Clone, Copy, Debug, PartialEq)] @@ -66,6 +70,10 @@ pub enum EventFilter { EVFILT_TIMER = libc::EVFILT_TIMER, } +#[cfg(any(target_os = "macos", + target_os = "freebsd", + target_os = "dragonfly"))] +type type_of_event_flag = u16; #[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))] @@ -96,6 +104,8 @@ bitflags!( } ); +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] +type type_of_event_flag = u32; #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] bitflags!( flags EventFlag: u32 { @@ -206,6 +216,44 @@ pub fn kqueue() -> Result { Errno::result(res) } +impl KEvent { + pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag, + fflags:FilterFlag, data: intptr_t, udata: uintptr_t) -> KEvent { + KEvent { kevent: libc::kevent { + ident: ident, + filter: filter as type_of_event_filter, + flags: flags.bits(), + fflags: fflags.bits(), + data: data, + udata: udata as type_of_udata + } } + } + + pub fn ident(&self) -> uintptr_t { + self.kevent.ident + } + + pub fn filter(&self) -> EventFilter { + unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) } + } + + pub fn flags(&self) -> EventFlag { + EventFlag::from_bits(self.kevent.flags).unwrap() + } + + pub fn fflags(&self) -> FilterFlag { + FilterFlag::from_bits(self.kevent.fflags).unwrap() + } + + pub fn data(&self) -> intptr_t { + self.kevent.data + } + + pub fn udata(&self) -> uintptr_t { + self.kevent.udata as uintptr_t + } +} + pub fn kevent(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], @@ -224,25 +272,10 @@ pub fn kevent(kq: RawFd, target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))] -pub fn kevent_ts(kq: RawFd, - changelist: &[KEvent], - eventlist: &mut [KEvent], - timeout_opt: Option) -> Result { - - let res = unsafe { - libc::kevent( - kq, - changelist.as_ptr() as *const libc::kevent, - changelist.len() as c_int, - eventlist.as_mut_ptr() as *mut libc::kevent, - eventlist.len() as c_int, - if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()}) - }; - - Errno::result(res).map(|r| r as usize) -} - +type type_of_nchanges = c_int; #[cfg(target_os = "netbsd")] +type type_of_nchanges = size_t; + pub fn kevent_ts(kq: RawFd, changelist: &[KEvent], eventlist: &mut [KEvent], @@ -252,9 +285,9 @@ pub fn kevent_ts(kq: RawFd, libc::kevent( kq, changelist.as_ptr() as *const libc::kevent, - changelist.len() as size_t, + changelist.len() as type_of_nchanges, eventlist.as_mut_ptr() as *mut libc::kevent, - eventlist.len() as size_t, + eventlist.len() as type_of_nchanges, if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()}) }; @@ -269,10 +302,35 @@ pub fn ev_set(ev: &mut KEvent, fflags: FilterFlag, udata: uintptr_t) { - ev.ident = ident as uintptr_t; - ev.filter = filter; - ev.flags = flags; - ev.fflags = fflags; - ev.data = 0; - ev.udata = udata; + ev.kevent.ident = ident as uintptr_t; + ev.kevent.filter = filter as type_of_event_filter; + ev.kevent.flags = flags.bits(); + ev.kevent.fflags = fflags.bits(); + ev.kevent.data = 0; + ev.kevent.udata = udata as type_of_udata; +} + +#[test] +fn test_struct_kevent() { + let udata : uintptr_t = 12345; + + let expected = libc::kevent{ident: 0xdeadbeef, + filter: libc::EVFILT_READ, + flags: libc::EV_DISPATCH | libc::EV_ADD, + fflags: libc::NOTE_CHILD | libc::NOTE_EXIT, + data: 0x1337, + udata: udata as type_of_udata}; + let actual = KEvent::new(0xdeadbeef, + EventFilter::EVFILT_READ, + EV_DISPATCH | EV_ADD, + NOTE_CHILD | NOTE_EXIT, + 0x1337, + udata); + assert!(expected.ident == actual.ident()); + assert!(expected.filter == actual.filter() as type_of_event_filter); + assert!(expected.flags == actual.flags().bits()); + assert!(expected.fflags == actual.fflags().bits()); + assert!(expected.data == actual.data()); + assert!(expected.udata == actual.udata() as type_of_udata); + assert!(mem::size_of::() == mem::size_of::()); } diff --git a/test/sys/mod.rs b/test/sys/mod.rs index 39455845d1..a5f3351df3 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -1,6 +1,3 @@ -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", - target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))] -mod test_event; mod test_socket; mod test_sockopt; mod test_termios; diff --git a/test/sys/test_event.rs b/test/sys/test_event.rs deleted file mode 100644 index f46e7c42e2..0000000000 --- a/test/sys/test_event.rs +++ /dev/null @@ -1,30 +0,0 @@ -use nix::sys::event; -use libc; -use std::mem::{size_of, size_of_val}; -use std::ptr; - -#[test] -/// Check that nix::event::KEvent has the same layout as libc::kevent -/// This would be easier with offsetof operators. -/// https://github.com/rust-lang/rfcs/issues/1144 -fn test_struct_kevent() { - let expected = libc::kevent{ident: 0, - filter: 0, - flags: 0, - fflags: 0, - data: 0, - udata: ptr::null_mut()}; - let actual = event::KEvent{ ident: 0, - filter: event::EventFilter::EVFILT_READ, - flags: event::EventFlag::empty(), - fflags: event::FilterFlag::empty(), - data: 0, - udata: 0}; - assert!(size_of::() == size_of::()); - assert!(size_of_val(&expected.ident) == size_of_val(&actual.ident)); - assert!(size_of_val(&expected.filter) == size_of_val(&actual.filter)); - assert!(size_of_val(&expected.flags) == size_of_val(&actual.flags)); - assert!(size_of_val(&expected.fflags) == size_of_val(&actual.fflags)); - assert!(size_of_val(&expected.data) == size_of_val(&actual.data)); - assert!(size_of_val(&expected.udata) == size_of_val(&actual.udata)); -} From b5ce388e41a581ca56460900261a668b929b64e8 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 2 Oct 2016 12:19:48 -0600 Subject: [PATCH 6/7] Use libc_bitflags! for EventFlag Don't use it for FilterFlag, because it triggers recursion limit reached error --- src/sys/event.rs | 75 ++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/src/sys/event.rs b/src/sys/event.rs index 28d8249528..d44963db03 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -70,62 +70,37 @@ pub enum EventFilter { EVFILT_TIMER = libc::EVFILT_TIMER, } -#[cfg(any(target_os = "macos", - target_os = "freebsd", - target_os = "dragonfly"))] -type type_of_event_flag = u16; -#[cfg(any(target_os = "macos", - target_os = "freebsd", - target_os = "dragonfly"))] -bitflags!( - flags EventFlag: u16 { - const EV_ADD = libc::EV_ADD, - const EV_CLEAR = libc::EV_CLEAR, - const EV_DELETE = libc::EV_DELETE, - const EV_DISABLE = libc::EV_DISABLE, - const EV_DISPATCH = libc::EV_DISPATCH, +#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly"))] +pub type type_of_event_flag = u16; +#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] +pub type type_of_event_flag = u32; +libc_bitflags!{ + flags EventFlag: type_of_event_flag { + EV_ADD, + EV_CLEAR, + EV_DELETE, + EV_DISABLE, + EV_DISPATCH, #[cfg(target_os = "freebsd")] - const EV_DROP = libc::EV_DROP, - const EV_ENABLE = libc::EV_ENABLE, - const EV_EOF = libc::EV_EOF, - const EV_ERROR = libc::EV_ERROR, + EV_DROP, + EV_ENABLE, + EV_EOF, + EV_ERROR, #[cfg(target_os = "macos")] - const EV_FLAG0 = libc::EV_FLAG0, - const EV_FLAG1 = libc::EV_FLAG1, + EV_FLAG0, + EV_FLAG1, #[cfg(target_os = "dragonfly")] - const EV_NODATA = libc::EV_NODATA, - const EV_ONESHOT = libc::EV_ONESHOT, + EV_NODATA, + EV_ONESHOT, #[cfg(target_os = "macos")] - const EV_OOBAND = libc::EV_OOBAND, + EV_OOBAND, #[cfg(target_os = "macos")] - const EV_POLL = libc::EV_POLL, - const EV_RECEIPT = libc::EV_RECEIPT, - const EV_SYSFLAGS = libc::EV_SYSFLAGS, + EV_POLL, + #[cfg(not(target_os = "openbsd"))] + EV_RECEIPT, + EV_SYSFLAGS, } -); - -#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] -type type_of_event_flag = u32; -#[cfg(any(target_os = "netbsd", target_os = "openbsd"))] -bitflags!( - flags EventFlag: u32 { - const EV_ADD = libc::EV_ADD, - const EV_DELETE = libc::EV_DELETE, - const EV_ENABLE = libc::EV_ENABLE, - const EV_DISABLE = libc::EV_DISABLE, - const EV_ONESHOT = libc::EV_ONESHOT, - const EV_CLEAR = libc::EV_CLEAR, - #[cfg(target_os = "openbsd")] - const EV_FLAG1 = libc::EV_FLAG1, - #[cfg(target_os = "netbsd")] - const EV_RECEIPT = libc::EV_RECEIPT, - const EV_DISPATCH = libc::EV_DISPATCH, - const EV_SYSFLAGS = libc::EV_SYSFLAGS, - const EV_FLAG1 = libc::EV_FLAG1, - const EV_EOF = libc::EV_EOF, - const EV_ERROR = libc::EV_ERROR, - } -); +} bitflags!( flags FilterFlag: u32 { From be9c1ff4844ae3bcdf48180b6c1600ab539ca971 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sun, 2 Oct 2016 12:31:30 -0600 Subject: [PATCH 7/7] Update CHANGELOG for PR #415 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d2e6bf805..4cf6b1c863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Added complete definitions for all kqueue-related constants on all supported + OSes + ([#415](https://github.com/nix-rust/nix/pull/415)) - Added `lseek` and `lseek64` in `::nix::unistd` ([#377](https://github.com/nix-rust/nix/pull/377)) - Added accessors `sigmask_mut` and `sigmask` to `UContext` in @@ -19,6 +22,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#386](https://github.com/nix-rust/nix/pull/386)) ### Changed +- Changed `KEvent` to an opaque structure that may only be modified by its + constructor and the `ev_set` method. + ([#415](https://github.com/nix-rust/nix/pull/415)) - Replaced the reexported integer constants for signals by the enumeration `Signal` in `::nix::sys::signal`. ([#362](https://github.com/nix-rust/nix/pull/362)) @@ -30,6 +36,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#362](https://github.com/nix-rust/nix/pull/362)) ### Fixed +- Fixed using kqueue with `EVFILT_USER` on FreeBSD + ([#415](https://github.com/nix-rust/nix/pull/415)) - Fixed the build problem for NetBSD (Note, that we currently do not support it, so it might already be broken again). ([#389](https://github.com/nix-rust/nix/pull/389))