diff --git a/Cargo.toml b/Cargo.toml index bda0121..1578bb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,9 @@ std = [] cfg-if = "1" log = "0.4.11" +[build-dependencies] +autocfg = "1" + [target.'cfg(any(unix, target_os = "fuchsia", target_os = "vxworks"))'.dependencies] libc = "0.2.77" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..16d6db5 --- /dev/null +++ b/build.rs @@ -0,0 +1,21 @@ +fn main() { + let cfg = match autocfg::AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + println!( + "cargo:warning=polling: failed to detect compiler features: {}", + e + ); + return; + } + }; + + // We use "no_*" instead of "has_*" here. For non-Cargo + // build tools that don't run build.rs, the negative + // allows us to treat the current Rust version as the + // latest stable version, for when version information + // isn't available. + if !cfg.probe_rustc_version(1, 63) { + autocfg::emit("polling_no_io_safety"); + } +} diff --git a/src/epoll.rs b/src/epoll.rs index e023331..8465131 100644 --- a/src/epoll.rs +++ b/src/epoll.rs @@ -2,10 +2,13 @@ use std::convert::TryInto; use std::io; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsRawFd, RawFd}; use std::ptr; use std::time::Duration; +#[cfg(not(polling_no_io_safety))] +use std::os::unix::io::{AsFd, BorrowedFd}; + use crate::Event; /// Interface to epoll. @@ -225,6 +228,20 @@ impl Poller { } } +impl AsRawFd for Poller { + fn as_raw_fd(&self) -> RawFd { + self.epoll_fd + } +} + +#[cfg(not(polling_no_io_safety))] +impl AsFd for Poller { + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: lifetime is bound by "self" + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + impl Drop for Poller { fn drop(&mut self) { log::trace!( diff --git a/src/kqueue.rs b/src/kqueue.rs index 8b0c5ec..d6c3d89 100644 --- a/src/kqueue.rs +++ b/src/kqueue.rs @@ -6,6 +6,9 @@ use std::os::unix::net::UnixStream; use std::ptr; use std::time::Duration; +#[cfg(not(polling_no_io_safety))] +use std::os::unix::io::{AsFd, BorrowedFd}; + use crate::Event; /// Interface to kqueue. @@ -177,6 +180,20 @@ impl Poller { } } +impl AsRawFd for Poller { + fn as_raw_fd(&self) -> RawFd { + self.kqueue_fd + } +} + +#[cfg(not(polling_no_io_safety))] +impl AsFd for Poller { + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: lifetime is bound by "self" + unsafe { BorrowedFd::borrow_raw(self.kqueue_fd) } + } +} + impl Drop for Poller { fn drop(&mut self) { log::trace!("drop: kqueue_fd={}", self.kqueue_fd); diff --git a/src/lib.rs b/src/lib.rs index bc129ae..4629a86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,6 +97,7 @@ cfg_if! { } else if #[cfg(any( target_os = "vxworks", target_os = "fuchsia", + target_os = "horizon", unix, ))] { mod poll; @@ -441,6 +442,61 @@ impl Poller { } } +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "illumos", + target_os = "solaris", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly", +))] +mod raw_fd_impl { + use crate::Poller; + use std::os::unix::io::{AsRawFd, RawFd}; + + #[cfg(not(polling_no_io_safety))] + use std::os::unix::io::{AsFd, BorrowedFd}; + + impl AsRawFd for Poller { + fn as_raw_fd(&self) -> RawFd { + self.poller.as_raw_fd() + } + } + + #[cfg(not(polling_no_io_safety))] + impl AsFd for Poller { + fn as_fd(&self) -> BorrowedFd<'_> { + self.poller.as_fd() + } + } +} + +#[cfg(windows)] +mod raw_handle_impl { + use crate::Poller; + use std::os::windows::io::{AsRawHandle, RawHandle}; + + #[cfg(not(polling_no_io_safety))] + use std::os::windows::io::{AsHandle, BorrowedHandle}; + + impl AsRawHandle for Poller { + fn as_raw_handle(&self) -> RawHandle { + self.poller.as_raw_handle() + } + } + + #[cfg(not(polling_no_io_safety))] + impl AsHandle for Poller { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.poller.as_handle() + } + } +} + impl fmt::Debug for Poller { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.poller.fmt(f) diff --git a/src/port.rs b/src/port.rs index 0d1a85e..a759768 100644 --- a/src/port.rs +++ b/src/port.rs @@ -6,6 +6,9 @@ use std::os::unix::net::UnixStream; use std::ptr; use std::time::Duration; +#[cfg(not(polling_no_io_safety))] +use std::os::unix::io::{AsFd, BorrowedFd}; + use crate::Event; /// Interface to event ports. @@ -143,6 +146,20 @@ impl Poller { } } +impl AsRawFd for Poller { + fn as_raw_fd(&self) -> RawFd { + self.port_fd + } +} + +#[cfg(not(polling_no_io_safety))] +impl AsFd for Poller { + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: lifetime is bound by self + unsafe { BorrowedFd::new(self.port_fd) } + } +} + impl Drop for Poller { fn drop(&mut self) { let _ = self.delete(self.read_stream.as_raw_fd()); diff --git a/src/wepoll.rs b/src/wepoll.rs index a440036..998f726 100644 --- a/src/wepoll.rs +++ b/src/wepoll.rs @@ -2,11 +2,14 @@ use std::convert::TryInto; use std::io; -use std::os::windows::io::RawSocket; +use std::os::windows::io::{AsRawHandle, RawHandle, RawSocket}; use std::ptr; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, Instant}; +#[cfg(not(polling_no_io_safety))] +use std::os::windows::io::{AsHandle, BorrowedHandle}; + use wepoll_ffi as we; use winapi::ctypes; @@ -166,6 +169,20 @@ impl Poller { } } +impl AsRawHandle for Poller { + fn as_raw_handle(&self) -> RawHandle { + self.handle as RawHandle + } +} + +#[cfg(not(polling_no_io_safety))] +impl AsHandle for Poller { + fn as_handle(&self) -> BorrowedHandle<'_> { + // SAFETY: lifetime is bound by "self" + unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } + } +} + impl Drop for Poller { fn drop(&mut self) { log::trace!("drop: handle={:?}", self.handle);