Skip to content

Commit f592678

Browse files
committed
feat: I/O safety for 'sys/timerfd'
1 parent a2356ab commit f592678

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

src/sys/timerfd.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,28 @@ pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
3333
use crate::unistd::read;
3434
use crate::{errno::Errno, Result};
3535
use libc::c_int;
36-
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
36+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
3737

3838
/// A timerfd instance. This is also a file descriptor, you can feed it to
39-
/// other interfaces consuming file descriptors, epoll for example.
39+
/// other interfaces taking file descriptors as arguments, [`epoll`] for example.
40+
///
41+
/// [`epoll`]: crate::sys::epoll
4042
#[derive(Debug)]
4143
pub struct TimerFd {
42-
fd: RawFd,
44+
fd: OwnedFd,
4345
}
4446

45-
impl AsRawFd for TimerFd {
46-
fn as_raw_fd(&self) -> RawFd {
47-
self.fd
47+
impl AsFd for TimerFd {
48+
fn as_fd(&self) -> BorrowedFd<'_> {
49+
self.fd.as_fd()
4850
}
4951
}
5052

5153
impl FromRawFd for TimerFd {
5254
unsafe fn from_raw_fd(fd: RawFd) -> Self {
53-
TimerFd { fd }
55+
TimerFd {
56+
fd: OwnedFd::from_raw_fd(fd),
57+
}
5458
}
5559
}
5660

@@ -97,7 +101,9 @@ impl TimerFd {
97101
Errno::result(unsafe {
98102
libc::timerfd_create(clockid as i32, flags.bits())
99103
})
100-
.map(|fd| Self { fd })
104+
.map(|fd| Self {
105+
fd: unsafe { OwnedFd::from_raw_fd(fd) },
106+
})
101107
}
102108

103109
/// Sets a new alarm on the timer.
@@ -145,7 +151,7 @@ impl TimerFd {
145151
let timerspec: TimerSpec = expiration.into();
146152
Errno::result(unsafe {
147153
libc::timerfd_settime(
148-
self.fd,
154+
self.fd.as_fd().as_raw_fd(),
149155
flags.bits(),
150156
timerspec.as_ref(),
151157
std::ptr::null_mut(),
@@ -159,7 +165,10 @@ impl TimerFd {
159165
pub fn get(&self) -> Result<Option<Expiration>> {
160166
let mut timerspec = TimerSpec::none();
161167
Errno::result(unsafe {
162-
libc::timerfd_gettime(self.fd, timerspec.as_mut())
168+
libc::timerfd_gettime(
169+
self.fd.as_fd().as_raw_fd(),
170+
timerspec.as_mut(),
171+
)
163172
})
164173
.map(|_| {
165174
if timerspec.as_ref().it_interval.tv_sec == 0
@@ -179,7 +188,7 @@ impl TimerFd {
179188
pub fn unset(&self) -> Result<()> {
180189
Errno::result(unsafe {
181190
libc::timerfd_settime(
182-
self.fd,
191+
self.fd.as_fd().as_raw_fd(),
183192
TimerSetTimeFlags::empty().bits(),
184193
TimerSpec::none().as_ref(),
185194
std::ptr::null_mut(),
@@ -192,7 +201,7 @@ impl TimerFd {
192201
///
193202
/// Note: If the alarm is unset, then you will wait forever.
194203
pub fn wait(&self) -> Result<()> {
195-
while let Err(e) = read(self.fd, &mut [0u8; 8]) {
204+
while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) {
196205
if e != Errno::EINTR {
197206
return Err(e);
198207
}
@@ -201,14 +210,3 @@ impl TimerFd {
201210
Ok(())
202211
}
203212
}
204-
205-
impl Drop for TimerFd {
206-
fn drop(&mut self) {
207-
if !std::thread::panicking() {
208-
let result = Errno::result(unsafe { libc::close(self.fd) });
209-
if let Err(Errno::EBADF) = result {
210-
panic!("close of TimerFd encountered EBADF");
211-
}
212-
}
213-
}
214-
}

0 commit comments

Comments
 (0)