diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2017-07-30 15:51:29 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2017-07-30 15:51:29 +0000 |
commit | f8768e93d8a8961b700b375d47fa3fe1ff2a346a (patch) | |
tree | 66683a388111db0d38947fe1dd6621313daf29ab | |
parent | 318441d9d9ecde4a976a5d9ae2c9172e7da7d9ce (diff) | |
parent | e19ffab8b1615f6cc617f0972317e0131ec8d62d (diff) | |
download | nix-f8768e93d8a8961b700b375d47fa3fe1ff2a346a.zip |
Merge #672
672: add poll module in Android r=Susurrus
`poll` functions are defined in Android as well.
libc is missing some constant, but once rust-lang/libc#663 is merged, it'll be good to merge here.
Closes #711
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/poll.rs | 82 | ||||
-rw-r--r-- | test/test.rs | 1 |
4 files changed, 82 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index d5064c9c..688b0dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). - On Linux and Android, added support for receiving `PTRACE_O_TRACESYSGOOD` events from `wait` and `waitpid` using `WaitStatus::PtraceSyscall` ([#566](https://github.com/nix-rust/nix/pull/566)). +- Added `nix::poll` module for all platforms + ([#672](https://github.com/nix-rust/nix/pull/672)) +- Added `nix::ppoll` function for FreeBSD and DragonFly + ([#672](https://github.com/nix-rust/nix/pull/672)) ### Changed - The `ioctl!` macro and its variants now allow the generated functions to have @@ -39,7 +39,6 @@ pub mod mqueue; pub mod pty; -#[cfg(any(target_os = "linux", target_os = "macos"))] pub mod poll; pub mod net; diff --git a/src/poll.rs b/src/poll.rs index afc5bd9c..60c31ace 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -1,11 +1,20 @@ -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::time::TimeSpec; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::signal::SigSet; +use std::os::unix::io::RawFd; use libc; use {Errno, Result}; +/// This is a wrapper around `libc::pollfd`. +/// +/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and +/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest +/// for a specific file descriptor. +/// +/// After a call to `poll` or `ppoll`, the events that occured can be +/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. #[repr(C)] #[derive(Clone, Copy)] pub struct PollFd { @@ -13,7 +22,9 @@ pub struct PollFd { } impl PollFd { - pub fn new(fd: libc::c_int, events: EventFlags) -> PollFd { + /// Creates a new `PollFd` specifying the events of interest + /// for a given file descriptor. + pub fn new(fd: RawFd, events: EventFlags) -> PollFd { PollFd { pollfd: libc::pollfd { fd: fd, @@ -23,26 +34,82 @@ impl PollFd { } } + /// Returns the events that occured in the last call to `poll` or `ppoll`. pub fn revents(&self) -> Option<EventFlags> { EventFlags::from_bits(self.pollfd.revents) } } libc_bitflags! { + /// These flags define the different events that can be monitored by `poll` and `ppoll` pub flags EventFlags: libc::c_short { + /// There is data to read. POLLIN, + /// There is some exceptional condition on the file descriptor. + /// + /// Possibilities include: + /// + /// * There is out-of-band data on a TCP socket (see + /// [tcp(7)](http://man7.org/linux/man-pages/man7/tcp.7.html)). + /// * A pseudoterminal master in packet mode has seen a state + /// change on the slave (see + /// [ioctl_tty(2)](http://man7.org/linux/man-pages/man2/ioctl_tty.2.html)). + /// * A cgroup.events file has been modified (see + /// [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)). POLLPRI, + /// Writing is now possible, though a write larger that the + /// available space in a socket or pipe will still block (unless + /// `O_NONBLOCK` is set). POLLOUT, + /// Equivalent to [`POLLIN`](constant.POLLIN.html) POLLRDNORM, + /// Equivalent to [`POLLOUT`](constant.POLLOUT.html) POLLWRNORM, + /// Priority band data can be read (generally unused on Linux). POLLRDBAND, + /// Priority data may be written. POLLWRBAND, + /// Error condition (only returned in + /// [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). + /// This bit is also set for a file descriptor referring to the + /// write end of a pipe when the read end has been closed. POLLERR, + /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). + /// Note that when reading from a channel such as a pipe or a stream + /// socket, this event merely indicates that the peer closed its + /// end of the channel. Subsequent reads from the channel will + /// return 0 (end of file) only after all outstanding data in the + /// channel has been consumed. POLLHUP, + /// Invalid request: `fd` not open (only returned in + /// [`PollFd::revents`](struct.PollFd.html#method.revents); + /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)). POLLNVAL, } } +/// `poll` waits for one of a set of file descriptors to become ready to perform I/O. +/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html)) +/// +/// `fds` contains all [`PollFd`](struct.PollFd.html) to poll. +/// The function will return as soon as any event occur for any of these `PollFd`s. +/// +/// The `timeout` argument specifies the number of milliseconds that `poll()` +/// should block waiting for a file descriptor to become ready. The call +/// will block until either: +/// +/// * a file descriptor becomes ready; +/// * the call is interrupted by a signal handler; or +/// * the timeout expires. +/// +/// Note that the timeout interval will be rounded up to the system clock +/// granularity, and kernel scheduling delays mean that the blocking +/// interval may overrun by a small amount. Specifying a negative value +/// in timeout means an infinite timeout. Specifying a timeout of zero +/// causes `poll()` to return immediately, even if no file descriptors are +/// ready. pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> { let res = unsafe { libc::poll(fds.as_mut_ptr() as *mut libc::pollfd, @@ -53,7 +120,14 @@ pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> { Errno::result(res) } -#[cfg(any(target_os = "linux", target_os = "android"))] +/// `ppoll()` allows an application to safely wait until either a file +/// descriptor becomes ready or until a signal is caught. +/// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html)) +/// +/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it +/// with the `sigmask` argument. +/// +#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> { diff --git a/test/test.rs b/test/test.rs index fab499ce..1d22b59a 100644 --- a/test/test.rs +++ b/test/test.rs @@ -15,7 +15,6 @@ mod test_fcntl; mod test_mq; mod test_net; mod test_nix_path; -#[cfg(any(target_os = "linux", target_os = "macos"))] mod test_poll; mod test_pty; #[cfg(any(target_os = "linux", target_os = "android"))] |