summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/epoll.rs64
-rw-r--r--src/sys/event.rs16
-rw-r--r--src/sys/eventfd.rs6
-rw-r--r--src/sys/memfd.rs6
-rw-r--r--src/sys/signalfd.rs38
-rw-r--r--src/sys/wait.rs15
6 files changed, 83 insertions, 62 deletions
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index 02c25d4d..36f9c17d 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -2,7 +2,7 @@ use crate::errno::Errno;
use crate::Result;
use libc::{self, c_int};
use std::mem;
-use std::os::unix::io::{FromRawFd,RawFd, OwnedFd, AsFd, AsRawFd};
+use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd};
libc_bitflags!(
pub struct EpollFlags: c_int {
@@ -78,22 +78,22 @@ impl EpollEvent {
/// # fn main() -> nix::Result<()> {
/// const DATA: u64 = 17;
/// const MILLIS: u64 = 100;
-///
+///
/// // Create epoll
/// let epoll = Epoll::new(EpollCreateFlags::empty())?;
-///
+///
/// // Create eventfd & Add event
-/// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) };
+/// let eventfd = eventfd(0, EfdFlags::empty())?;
/// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?;
-///
+///
/// // Arm eventfd & Time wait
/// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?;
/// let now = Instant::now();
-///
+///
/// // Wait on event
/// let mut events = [EpollEvent::empty()];
/// epoll.wait(&mut events, MILLIS as isize)?;
-///
+///
/// // Assert data correct & timeout didn't occur
/// assert_eq!(events[0].data(), DATA);
/// assert!(now.elapsed() < Duration::from_millis(MILLIS));
@@ -104,7 +104,7 @@ impl EpollEvent {
pub struct Epoll(pub OwnedFd);
impl Epoll {
/// Creates a new epoll instance and returns a file descriptor referring to that instance.
- ///
+ ///
/// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html).
pub fn new(flags: EpollCreateFlags) -> Result<Self> {
let res = unsafe { libc::epoll_create1(flags.bits()) };
@@ -113,30 +113,38 @@ impl Epoll {
Ok(Self(owned_fd))
}
/// Add an entry to the interest list of the epoll file descriptor for
- /// specified in events.
- ///
+ /// specified in events.
+ ///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`.
pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> {
- self.epoll_ctl(EpollOp::EpollCtlAdd,fd,&mut event)
+ self.epoll_ctl(EpollOp::EpollCtlAdd, fd, &mut event)
}
/// Remove (deregister) the target file descriptor `fd` from the interest list.
- ///
+ ///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` .
pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> {
- self.epoll_ctl(EpollOp::EpollCtlDel,fd,None)
+ self.epoll_ctl(EpollOp::EpollCtlDel, fd, None)
}
/// Change the settings associated with `fd` in the interest list to the new settings specified
/// in `event`.
- ///
+ ///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`.
- pub fn modify<Fd: AsFd>(&self,fd: Fd, event: &mut EpollEvent) -> Result<()> {
- self.epoll_ctl(EpollOp::EpollCtlMod,fd,event)
+ pub fn modify<Fd: AsFd>(
+ &self,
+ fd: Fd,
+ event: &mut EpollEvent,
+ ) -> Result<()> {
+ self.epoll_ctl(EpollOp::EpollCtlMod, fd, event)
}
/// Waits for I/O events, blocking the calling thread if no events are currently available.
/// (This can be thought of as fetching items from the ready list of the epoll instance.)
- ///
+ ///
/// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html)
- pub fn wait(&self, events: &mut [EpollEvent], timeout: isize) -> Result<usize> {
+ pub fn wait(
+ &self,
+ events: &mut [EpollEvent],
+ timeout: isize,
+ ) -> Result<usize> {
let res = unsafe {
libc::epoll_wait(
self.0.as_raw_fd(),
@@ -145,15 +153,15 @@ impl Epoll {
timeout as c_int,
)
};
-
+
Errno::result(res).map(|r| r as usize)
}
/// This system call is used to add, modify, or remove entries in the interest list of the epoll
/// instance referred to by `self`. It requests that the operation `op` be performed for the
/// target file descriptor, `fd`.
- ///
+ ///
/// When possible prefer [`Epoll::add`], [`Epoll::delete`] and [`Epoll::modify`].
- ///
+ ///
/// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html)
fn epoll_ctl<'a, Fd: AsFd, T>(
&self,
@@ -165,9 +173,17 @@ impl Epoll {
T: Into<Option<&'a mut EpollEvent>>,
{
let event: Option<&mut EpollEvent> = event.into();
- let ptr = event.map(|x|&mut x.event as *mut libc::epoll_event).unwrap_or(std::ptr::null_mut());
+ let ptr = event
+ .map(|x| &mut x.event as *mut libc::epoll_event)
+ .unwrap_or(std::ptr::null_mut());
unsafe {
- Errno::result(libc::epoll_ctl(self.0.as_raw_fd(), op as c_int, fd.as_fd().as_raw_fd(), ptr)).map(drop)
+ Errno::result(libc::epoll_ctl(
+ self.0.as_raw_fd(),
+ op as c_int,
+ fd.as_fd().as_raw_fd(),
+ ptr,
+ ))
+ .map(drop)
}
}
}
@@ -231,4 +247,4 @@ pub fn epoll_wait(
};
Errno::result(res).map(|r| r as usize)
-} \ No newline at end of file
+}
diff --git a/src/sys/event.rs b/src/sys/event.rs
index d8ad628e..f21ba173 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -8,7 +8,7 @@ use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t};
use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t};
use std::convert::TryInto;
use std::mem;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd};
use std::ptr;
// Redefine kevent in terms of programmer-friendly enums and bitfields.
@@ -207,10 +207,10 @@ libc_bitflags!(
}
);
-pub fn kqueue() -> Result<RawFd> {
+pub fn kqueue() -> Result<OwnedFd> {
let res = unsafe { libc::kqueue() };
- Errno::result(res)
+ Errno::result(res).map(|fd| unsafe { OwnedFd::from_raw_fd(fd) })
}
// KEvent can't derive Send because on some operating systems, udata is defined
@@ -267,8 +267,8 @@ impl KEvent {
}
}
-pub fn kevent(
- kq: RawFd,
+pub fn kevent<Fd: AsFd>(
+ kq: Fd,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_ms: usize,
@@ -293,15 +293,15 @@ type type_of_nchanges = c_int;
#[cfg(target_os = "netbsd")]
type type_of_nchanges = size_t;
-pub fn kevent_ts(
- kq: RawFd,
+pub fn kevent_ts<Fd: AsFd>(
+ kq: Fd,
changelist: &[KEvent],
eventlist: &mut [KEvent],
timeout_opt: Option<timespec>,
) -> Result<usize> {
let res = unsafe {
libc::kevent(
- kq,
+ kq.as_fd().as_raw_fd(),
changelist.as_ptr() as *const libc::kevent,
changelist.len() as type_of_nchanges,
eventlist.as_mut_ptr() as *mut libc::kevent,
diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs
index cd906720..f1723519 100644
--- a/src/sys/eventfd.rs
+++ b/src/sys/eventfd.rs
@@ -1,6 +1,6 @@
use crate::errno::Errno;
use crate::Result;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{FromRawFd, OwnedFd};
libc_bitflags! {
pub struct EfdFlags: libc::c_int {
@@ -10,8 +10,8 @@ libc_bitflags! {
}
}
-pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
+pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> {
let res = unsafe { libc::eventfd(initval, flags.bits()) };
- Errno::result(res).map(|r| r as RawFd)
+ Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) })
}
diff --git a/src/sys/memfd.rs b/src/sys/memfd.rs
index ad9345e8..f349a743 100644
--- a/src/sys/memfd.rs
+++ b/src/sys/memfd.rs
@@ -1,7 +1,7 @@
//! Interfaces for managing memory-backed files.
use cfg_if::cfg_if;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
use crate::errno::Errno;
use crate::Result;
@@ -40,7 +40,7 @@ libc_bitflags!(
/// For more information, see [`memfd_create(2)`].
///
/// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html
-pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
+pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> {
let res = unsafe {
cfg_if! {
if #[cfg(all(
@@ -60,5 +60,5 @@ pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
}
};
- Errno::result(res).map(|r| r as RawFd)
+ Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r as RawFd) })
}
diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs
index 095e5908..2b80ea64 100644
--- a/src/sys/signalfd.rs
+++ b/src/sys/signalfd.rs
@@ -17,12 +17,11 @@
//! signal handlers.
use crate::errno::Errno;
pub use crate::sys::signal::{self, SigSet};
-use crate::unistd;
use crate::Result;
pub use libc::signalfd_siginfo as siginfo;
use std::mem;
-use std::os::unix::io::{AsRawFd, RawFd};
+use std::os::unix::io::{AsRawFd, RawFd, FromRawFd, OwnedFd, AsFd, BorrowedFd};
libc_bitflags! {
pub struct SfdFlags: libc::c_int {
@@ -31,7 +30,6 @@ libc_bitflags! {
}
}
-pub const SIGNALFD_NEW: RawFd = -1;
#[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")]
pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
@@ -46,13 +44,19 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>();
/// signalfd (the default handler will be invoked instead).
///
/// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html)
-pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
+#[deprecated(since = "0.27.0", note = "Use SignalFd instead")]
+pub fn signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
+ _signalfd(fd, mask, flags)
+}
+
+fn _signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> {
+ let raw_fd = fd.map_or(-1, |x|x.as_fd().as_raw_fd());
unsafe {
Errno::result(libc::signalfd(
- fd as libc::c_int,
+ raw_fd,
mask.as_ref(),
flags.bits(),
- ))
+ )).map(|raw_fd|FromRawFd::from_raw_fd(raw_fd))
}
}
@@ -82,8 +86,8 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
/// Err(err) => (), // some error happend
/// }
/// ```
-#[derive(Debug, Eq, Hash, PartialEq)]
-pub struct SignalFd(RawFd);
+#[derive(Debug)]
+pub struct SignalFd(OwnedFd);
impl SignalFd {
pub fn new(mask: &SigSet) -> Result<SignalFd> {
@@ -91,13 +95,13 @@ impl SignalFd {
}
pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
- let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
+ let fd = _signalfd(None::<OwnedFd>, mask, flags)?;
Ok(SignalFd(fd))
}
pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
- signalfd(self.0, mask, SfdFlags::empty()).map(drop)
+ _signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop)
}
pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
@@ -105,7 +109,7 @@ impl SignalFd {
let size = mem::size_of_val(&buffer);
let res = Errno::result(unsafe {
- libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size)
+ libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr() as *mut libc::c_void, size)
})
.map(|r| r as usize);
match res {
@@ -117,18 +121,14 @@ impl SignalFd {
}
}
-impl Drop for SignalFd {
- fn drop(&mut self) {
- let e = unistd::close(self.0);
- if !std::thread::panicking() && e == Err(Errno::EBADF) {
- panic!("Closing an invalid file descriptor!");
- };
+impl AsFd for SignalFd {
+ fn as_fd(&self) -> BorrowedFd {
+ self.0.as_fd()
}
}
-
impl AsRawFd for SignalFd {
fn as_raw_fd(&self) -> RawFd {
- self.0
+ self.0.as_raw_fd()
}
}
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index b6524e86..f7a63ffc 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -10,7 +10,7 @@ use std::convert::TryFrom;
target_os = "android",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{AsRawFd, BorrowedFd};
libc_bitflags!(
/// Controls the behavior of [`waitpid`].
@@ -343,8 +343,8 @@ pub fn wait() -> Result<WaitStatus> {
target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Id {
+#[derive(Debug)]
+pub enum Id<'fd> {
/// Wait for any child
All,
/// Wait for the child whose process ID matches the given PID
@@ -355,7 +355,11 @@ pub enum Id {
PGid(Pid),
/// Wait for the child referred to by the given PID file descriptor
#[cfg(any(target_os = "android", target_os = "linux"))]
- PIDFd(RawFd),
+ PIDFd(BorrowedFd<'fd>),
+ /// A helper variant to resolve the unused parameter (`'fd`) problem on platforms
+ /// other than Linux and Android.
+ #[doc(hidden)]
+ _Unreachable(std::marker::PhantomData<&'fd std::convert::Infallible>),
}
/// Wait for a process to change status
@@ -373,7 +377,8 @@ pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> {
Id::Pid(pid) => (libc::P_PID, pid.as_raw() as libc::id_t),
Id::PGid(pid) => (libc::P_PGID, pid.as_raw() as libc::id_t),
#[cfg(any(target_os = "android", target_os = "linux"))]
- Id::PIDFd(fd) => (libc::P_PIDFD, fd as libc::id_t),
+ Id::PIDFd(fd) => (libc::P_PIDFD, fd.as_raw_fd() as libc::id_t),
+ Id::_Unreachable(_) => unreachable!("This variant could never be constructed"),
};
let siginfo = unsafe {