summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorSteve Lau <stevelauc@outlook.com>2022-12-09 15:33:27 +0800
committerSteve Lau <stevelauc@outlook.com>2022-12-09 15:33:27 +0800
commitf592678301e30fa51b0149ca37f42b5c7ea5657e (patch)
tree41ce883f0bbd0c239ada484f07120d53b9d66184 /src/sys
parenta2356abe578dc822dbaf4386fbc17a63385ba0f8 (diff)
downloadnix-f592678301e30fa51b0149ca37f42b5c7ea5657e.zip
feat: I/O safety for 'sys/timerfd'
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/timerfd.rs44
1 files changed, 21 insertions, 23 deletions
diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs
index a35fc927..90a05a8c 100644
--- a/src/sys/timerfd.rs
+++ b/src/sys/timerfd.rs
@@ -33,24 +33,28 @@ pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
use crate::unistd::read;
use crate::{errno::Errno, Result};
use libc::c_int;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
/// A timerfd instance. This is also a file descriptor, you can feed it to
-/// other interfaces consuming file descriptors, epoll for example.
+/// other interfaces taking file descriptors as arguments, [`epoll`] for example.
+///
+/// [`epoll`]: crate::sys::epoll
#[derive(Debug)]
pub struct TimerFd {
- fd: RawFd,
+ fd: OwnedFd,
}
-impl AsRawFd for TimerFd {
- fn as_raw_fd(&self) -> RawFd {
- self.fd
+impl AsFd for TimerFd {
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ self.fd.as_fd()
}
}
impl FromRawFd for TimerFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
- TimerFd { fd }
+ TimerFd {
+ fd: OwnedFd::from_raw_fd(fd),
+ }
}
}
@@ -97,7 +101,9 @@ impl TimerFd {
Errno::result(unsafe {
libc::timerfd_create(clockid as i32, flags.bits())
})
- .map(|fd| Self { fd })
+ .map(|fd| Self {
+ fd: unsafe { OwnedFd::from_raw_fd(fd) },
+ })
}
/// Sets a new alarm on the timer.
@@ -145,7 +151,7 @@ impl TimerFd {
let timerspec: TimerSpec = expiration.into();
Errno::result(unsafe {
libc::timerfd_settime(
- self.fd,
+ self.fd.as_fd().as_raw_fd(),
flags.bits(),
timerspec.as_ref(),
std::ptr::null_mut(),
@@ -159,7 +165,10 @@ impl TimerFd {
pub fn get(&self) -> Result<Option<Expiration>> {
let mut timerspec = TimerSpec::none();
Errno::result(unsafe {
- libc::timerfd_gettime(self.fd, timerspec.as_mut())
+ libc::timerfd_gettime(
+ self.fd.as_fd().as_raw_fd(),
+ timerspec.as_mut(),
+ )
})
.map(|_| {
if timerspec.as_ref().it_interval.tv_sec == 0
@@ -179,7 +188,7 @@ impl TimerFd {
pub fn unset(&self) -> Result<()> {
Errno::result(unsafe {
libc::timerfd_settime(
- self.fd,
+ self.fd.as_fd().as_raw_fd(),
TimerSetTimeFlags::empty().bits(),
TimerSpec::none().as_ref(),
std::ptr::null_mut(),
@@ -192,7 +201,7 @@ impl TimerFd {
///
/// Note: If the alarm is unset, then you will wait forever.
pub fn wait(&self) -> Result<()> {
- while let Err(e) = read(self.fd, &mut [0u8; 8]) {
+ while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) {
if e != Errno::EINTR {
return Err(e);
}
@@ -201,14 +210,3 @@ impl TimerFd {
Ok(())
}
}
-
-impl Drop for TimerFd {
- fn drop(&mut self) {
- if !std::thread::panicking() {
- let result = Errno::result(unsafe { libc::close(self.fd) });
- if let Err(Errno::EBADF) = result {
- panic!("close of TimerFd encountered EBADF");
- }
- }
- }
-}