Skip to content

Commit 5200f6c

Browse files
committed
Use OwnedFd in epoll and kqueue selectors
1 parent 8d30e76 commit 5200f6c

File tree

5 files changed

+32
-55
lines changed

5 files changed

+32
-55
lines changed

src/sys/unix/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#[allow(unused_macros)]
55
macro_rules! syscall {
66
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
7+
#[allow(unused_unsafe)]
78
let res = unsafe { libc::$fn($($arg, )*) };
89
if res < 0 {
910
Err(std::io::Error::last_os_error())

src/sys/unix/selector/epoll.rs

+14-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::os::fd::{AsRawFd, RawFd};
1+
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
22
#[cfg(debug_assertions)]
33
use std::sync::atomic::{AtomicUsize, Ordering};
44
use std::time::Duration;
@@ -16,20 +16,22 @@ static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
1616
pub struct Selector {
1717
#[cfg(debug_assertions)]
1818
id: usize,
19-
ep: RawFd,
19+
ep: OwnedFd,
2020
}
2121

2222
impl Selector {
2323
pub fn new() -> io::Result<Selector> {
24+
// SAFETY: `epoll_create1(2)` ensures the fd is valid.
25+
let ep = unsafe { OwnedFd::from_raw_fd(syscall!(epoll_create1(libc::EPOLL_CLOEXEC))?) };
2426
Ok(Selector {
2527
#[cfg(debug_assertions)]
2628
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
27-
ep: syscall!(epoll_create1(libc::EPOLL_CLOEXEC))?,
29+
ep,
2830
})
2931
}
3032

3133
pub fn try_clone(&self) -> io::Result<Selector> {
32-
syscall!(fcntl(self.ep, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|ep| Selector {
34+
self.ep.try_clone().map(|ep| Selector {
3335
// It's the same selector, so we use the same id.
3436
#[cfg(debug_assertions)]
3537
id: self.id,
@@ -52,7 +54,7 @@ impl Selector {
5254

5355
events.clear();
5456
syscall!(epoll_wait(
55-
self.ep,
57+
self.ep.as_raw_fd(),
5658
events.as_mut_ptr(),
5759
events.capacity() as i32,
5860
timeout,
@@ -72,7 +74,8 @@ impl Selector {
7274
_pad: 0,
7375
};
7476

75-
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_ADD, fd, &mut event)).map(|_| ())
77+
let ep = self.ep.as_raw_fd();
78+
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_ADD, fd, &mut event)).map(|_| ())
7679
}
7780

7881
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
@@ -83,11 +86,13 @@ impl Selector {
8386
_pad: 0,
8487
};
8588

86-
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_MOD, fd, &mut event)).map(|_| ())
89+
let ep = self.ep.as_raw_fd();
90+
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_MOD, fd, &mut event)).map(|_| ())
8791
}
8892

8993
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
90-
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_DEL, fd, ptr::null_mut())).map(|_| ())
94+
let ep = self.ep.as_raw_fd();
95+
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_DEL, fd, ptr::null_mut())).map(|_| ())
9196
}
9297
}
9398

@@ -102,15 +107,7 @@ cfg_io_source! {
102107

103108
impl AsRawFd for Selector {
104109
fn as_raw_fd(&self) -> RawFd {
105-
self.ep
106-
}
107-
}
108-
109-
impl Drop for Selector {
110-
fn drop(&mut self) {
111-
if let Err(err) = syscall!(close(self.ep)) {
112-
error!("error closing epoll: {}", err);
113-
}
110+
self.ep.as_raw_fd()
114111
}
115112
}
116113

src/sys/unix/selector/kqueue.rs

+17-24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{Interest, Token};
22
use std::mem::{self, MaybeUninit};
33
use std::ops::{Deref, DerefMut};
4-
use std::os::fd::{AsRawFd, RawFd};
4+
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
55
#[cfg(debug_assertions)]
66
use std::sync::atomic::{AtomicUsize, Ordering};
77
use std::time::Duration;
@@ -65,24 +65,23 @@ macro_rules! kevent {
6565
pub struct Selector {
6666
#[cfg(debug_assertions)]
6767
id: usize,
68-
kq: RawFd,
68+
kq: OwnedFd,
6969
}
7070

7171
impl Selector {
7272
pub fn new() -> io::Result<Selector> {
73-
let kq = syscall!(kqueue())?;
74-
let selector = Selector {
73+
// SAFETY: `kqueue(2)` ensures the fd is valid.
74+
let kq = unsafe { OwnedFd::from_raw_fd(syscall!(kqueue())?) };
75+
syscall!(fcntl(kq.as_raw_fd(), libc::F_SETFD, libc::FD_CLOEXEC))?;
76+
Ok(Selector {
7577
#[cfg(debug_assertions)]
7678
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
7779
kq,
78-
};
79-
80-
syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC))?;
81-
Ok(selector)
80+
})
8281
}
8382

8483
pub fn try_clone(&self) -> io::Result<Selector> {
85-
syscall!(fcntl(self.kq, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|kq| Selector {
84+
self.kq.try_clone().map(|kq| Selector {
8685
// It's the same selector, so we use the same id.
8786
#[cfg(debug_assertions)]
8887
id: self.id,
@@ -106,7 +105,7 @@ impl Selector {
106105

107106
events.clear();
108107
syscall!(kevent(
109-
self.kq,
108+
self.kq.as_raw_fd(),
110109
ptr::null(),
111110
0,
112111
events.as_mut_ptr(),
@@ -156,7 +155,7 @@ impl Selector {
156155
// the array.
157156
slice::from_raw_parts_mut(changes[0].as_mut_ptr(), n_changes)
158157
};
159-
kevent_register(self.kq, changes, &[libc::EPIPE as i64])
158+
kevent_register(self.kq.as_raw_fd(), changes, &[libc::EPIPE as i64])
160159
}
161160

162161
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
@@ -186,7 +185,7 @@ impl Selector {
186185
//
187186
// For the explanation of ignoring `EPIPE` see `register`.
188187
kevent_register(
189-
self.kq,
188+
self.kq.as_raw_fd(),
190189
&mut changes,
191190
&[libc::ENOENT as i64, libc::EPIPE as i64],
192191
)
@@ -204,7 +203,7 @@ impl Selector {
204203
// the ENOENT error when it comes up. The ENOENT error informs us that
205204
// the filter wasn't there in first place, but we don't really care
206205
// about that since our goal is to remove it.
207-
kevent_register(self.kq, &mut changes, &[libc::ENOENT as i64])
206+
kevent_register(self.kq.as_raw_fd(), &mut changes, &[libc::ENOENT as i64])
208207
}
209208

210209
// Used by `Waker`.
@@ -224,7 +223,8 @@ impl Selector {
224223
token.0
225224
);
226225

227-
syscall!(kevent(self.kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
226+
let kq = self.kq.as_raw_fd();
227+
syscall!(kevent(kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
228228
if (kevent.flags & libc::EV_ERROR) != 0 && kevent.data != 0 {
229229
Err(io::Error::from_raw_os_error(kevent.data as i32))
230230
} else {
@@ -250,7 +250,8 @@ impl Selector {
250250
);
251251
kevent.fflags = libc::NOTE_TRIGGER;
252252

253-
syscall!(kevent(self.kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
253+
let kq = self.kq.as_raw_fd();
254+
syscall!(kevent(kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
254255
if (kevent.flags & libc::EV_ERROR) != 0 && kevent.data != 0 {
255256
Err(io::Error::from_raw_os_error(kevent.data as i32))
256257
} else {
@@ -314,15 +315,7 @@ cfg_io_source! {
314315

315316
impl AsRawFd for Selector {
316317
fn as_raw_fd(&self) -> RawFd {
317-
self.kq
318-
}
319-
}
320-
321-
impl Drop for Selector {
322-
fn drop(&mut self) {
323-
if let Err(err) = syscall!(close(self.kq)) {
324-
error!("error closing kqueue: {}", err);
325-
}
318+
self.kq.as_raw_fd()
326319
}
327320
}
328321

src/sys/unix/selector/mod.rs

-10
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,3 @@ mod kqueue;
7878
),
7979
))]
8080
pub(crate) use self::kqueue::{event, Event, Events, Selector};
81-
82-
/// Lowest file descriptor used in `Selector::try_clone`.
83-
///
84-
/// # Notes
85-
///
86-
/// Usually fds 0, 1 and 2 are standard in, out and error. Some application
87-
/// blindly assume this to be true, which means using any one of those a select
88-
/// could result in some interesting and unexpected errors. Avoid that by using
89-
/// an fd that doesn't have a pre-determined usage.
90-
const LOWEST_FD: libc::c_int = 3;

src/sys/unix/selector/poll.rs

-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use std::sync::{Arc, Condvar, Mutex};
1111
use std::time::Duration;
1212
use std::{cmp, fmt, io};
1313

14-
use crate::sys::unix::selector::LOWEST_FD;
1514
use crate::sys::unix::waker::WakerInternal;
1615
use crate::{Interest, Token};
1716

@@ -34,9 +33,6 @@ impl Selector {
3433
}
3534

3635
pub fn try_clone(&self) -> io::Result<Selector> {
37-
// Just to keep the compiler happy :)
38-
let _ = LOWEST_FD;
39-
4036
let state = self.state.clone();
4137

4238
Ok(Selector { state })

0 commit comments

Comments
 (0)