1 //! Linux `epoll` support.
2 //!
3 //! # Examples
4 //!
5 //! ```no_run
6 //! # #[cfg(feature = "net")]
7 //! # fn main() -> std::io::Result<()> {
8 //! use rustix::event::epoll;
9 //! use rustix::fd::AsFd;
10 //! use rustix::io::{ioctl_fionbio, read, write};
11 //! use rustix::net::{
12 //!     accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, SocketAddrV4, SocketType,
13 //! };
14 //! use std::collections::HashMap;
15 //! use std::os::unix::io::AsRawFd;
16 //!
17 //! // Create a socket and listen on it.
18 //! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, None)?;
19 //! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
20 //! listen(&listen_sock, 1)?;
21 //!
22 //! // Create an epoll object. Using `Owning` here means the epoll object will
23 //! // take ownership of the file descriptors registered with it.
24 //! let epoll = epoll::create(epoll::CreateFlags::CLOEXEC)?;
25 //!
26 //! // Register the socket with the epoll object.
27 //! epoll::add(
28 //!     &epoll,
29 //!     &listen_sock,
30 //!     epoll::EventData::new_u64(1),
31 //!     epoll::EventFlags::IN,
32 //! )?;
33 //!
34 //! // Keep track of the sockets we've opened.
35 //! let mut next_id = epoll::EventData::new_u64(2);
36 //! let mut sockets = HashMap::new();
37 //!
38 //! // Process events.
39 //! let mut event_list = epoll::EventVec::with_capacity(4);
40 //! loop {
41 //!     epoll::wait(&epoll, &mut event_list, -1)?;
42 //!     for event in &event_list {
43 //!         let target = event.data;
44 //!         if target.u64() == 1 {
45 //!             // Accept a new connection, set it to non-blocking, and
46 //!             // register to be notified when it's ready to write to.
47 //!             let conn_sock = accept(&listen_sock)?;
48 //!             ioctl_fionbio(&conn_sock, true)?;
49 //!             epoll::add(
50 //!                 &epoll,
51 //!                 &conn_sock,
52 //!                 next_id,
53 //!                 epoll::EventFlags::OUT | epoll::EventFlags::ET,
54 //!             )?;
55 //!
56 //!             // Keep track of the socket.
57 //!             sockets.insert(next_id, conn_sock);
58 //!             next_id = epoll::EventData::new_u64(next_id.u64() + 1);
59 //!         } else {
60 //!             // Write a message to the stream and then unregister it.
61 //!             let target = sockets.remove(&target).unwrap();
62 //!             write(&target, b"hello\n")?;
63 //!             let _ = epoll::delete(&epoll, &target)?;
64 //!         }
65 //!     }
66 //! }
67 //! # }
68 //! # #[cfg(not(feature = "net"))]
69 //! # fn main() {}
70 //! ```
71 
72 use crate::backend::c;
73 #[cfg(feature = "alloc")]
74 use crate::backend::conv::ret_u32;
75 use crate::backend::conv::{ret, ret_owned_fd};
76 use crate::fd::{AsFd, AsRawFd, OwnedFd};
77 use crate::io;
78 use crate::utils::as_mut_ptr;
79 #[cfg(feature = "alloc")]
80 use alloc::vec::Vec;
81 use bitflags::bitflags;
82 use core::ffi::c_void;
83 use core::hash::{Hash, Hasher};
84 use core::ptr::null_mut;
85 use core::slice;
86 
87 bitflags! {
88     /// `EPOLL_*` for use with [`new`].
89     #[repr(transparent)]
90     #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
91     pub struct CreateFlags: u32 {
92         /// `EPOLL_CLOEXEC`
93         const CLOEXEC = bitcast!(c::EPOLL_CLOEXEC);
94 
95         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
96         const _ = !0;
97     }
98 }
99 
100 bitflags! {
101     /// `EPOLL*` for use with [`add`].
102     #[repr(transparent)]
103     #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
104     pub struct EventFlags: u32 {
105         /// `EPOLLIN`
106         const IN = bitcast!(c::EPOLLIN);
107 
108         /// `EPOLLOUT`
109         const OUT = bitcast!(c::EPOLLOUT);
110 
111         /// `EPOLLPRI`
112         const PRI = bitcast!(c::EPOLLPRI);
113 
114         /// `EPOLLERR`
115         const ERR = bitcast!(c::EPOLLERR);
116 
117         /// `EPOLLHUP`
118         const HUP = bitcast!(c::EPOLLHUP);
119 
120         /// `EPOLLRDNORM`
121         const RDNORM = bitcast!(c::EPOLLRDNORM);
122 
123         /// `EPOLLRDBAND`
124         const RDBAND = bitcast!(c::EPOLLRDBAND);
125 
126         /// `EPOLLWRNORM`
127         const WRNORM = bitcast!(c::EPOLLWRNORM);
128 
129         /// `EPOLLWRBAND`
130         const WRBAND = bitcast!(c::EPOLLWRBAND);
131 
132         /// `EPOLLMSG`
133         const MSG = bitcast!(c::EPOLLMSG);
134 
135         /// `EPOLLRDHUP`
136         const RDHUP = bitcast!(c::EPOLLRDHUP);
137 
138         /// `EPOLLET`
139         const ET = bitcast!(c::EPOLLET);
140 
141         /// `EPOLLONESHOT`
142         const ONESHOT = bitcast!(c::EPOLLONESHOT);
143 
144         /// `EPOLLWAKEUP`
145         const WAKEUP = bitcast!(c::EPOLLWAKEUP);
146 
147         /// `EPOLLEXCLUSIVE`
148         #[cfg(not(target_os = "android"))]
149         const EXCLUSIVE = bitcast!(c::EPOLLEXCLUSIVE);
150 
151         /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags>
152         const _ = !0;
153     }
154 }
155 
156 /// `epoll_create1(flags)`—Creates a new epoll object.
157 ///
158 /// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
159 /// descriptor from being implicitly passed across `exec` boundaries.
160 #[inline]
161 #[doc(alias = "epoll_create1")]
create(flags: CreateFlags) -> io::Result<OwnedFd>162 pub fn create(flags: CreateFlags) -> io::Result<OwnedFd> {
163     // SAFETY: We're calling `epoll_create1` via FFI and we know how it
164     // behaves.
165     unsafe { ret_owned_fd(c::epoll_create1(bitflags_bits!(flags))) }
166 }
167 
168 /// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an epoll
169 /// object.
170 ///
171 /// This registers interest in any of the events set in `events` occurring on
172 /// the file descriptor associated with `data`.
173 ///
174 /// If [`delete`] is not called on the I/O source passed into this function
175 /// before the I/O source is `close`d, then the `epoll` will act as if the I/O
176 /// source is still registered with it. This can lead to spurious events being
177 /// returned from [`wait`]. If a file descriptor is an
178 /// `Arc<dyn SystemResource>`, then `epoll` can be thought to maintain a
179 /// `Weak<dyn SystemResource>` to the file descriptor.
180 #[doc(alias = "epoll_ctl")]
add( epoll: impl AsFd, source: impl AsFd, data: EventData, event_flags: EventFlags, ) -> io::Result<()>181 pub fn add(
182     epoll: impl AsFd,
183     source: impl AsFd,
184     data: EventData,
185     event_flags: EventFlags,
186 ) -> io::Result<()> {
187     // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
188     // behaves. We use our own `Event` struct instead of libc's because
189     // ours preserves pointer provenance instead of just using a `u64`,
190     // and we have tests elsewhere for layout equivalence.
191     unsafe {
192         let raw_fd = source.as_fd().as_raw_fd();
193         ret(c::epoll_ctl(
194             epoll.as_fd().as_raw_fd(),
195             c::EPOLL_CTL_ADD,
196             raw_fd,
197             as_mut_ptr(&mut Event {
198                 flags: event_flags,
199                 data,
200                 #[cfg(target_os = "redox")]
201                 _pad: 0,
202             })
203             .cast(),
204         ))
205     }
206 }
207 
208 /// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in a
209 /// given epoll object.
210 ///
211 /// This sets the events of interest with `target` to `events`.
212 #[doc(alias = "epoll_ctl")]
modify( epoll: impl AsFd, source: impl AsFd, data: EventData, event_flags: EventFlags, ) -> io::Result<()>213 pub fn modify(
214     epoll: impl AsFd,
215     source: impl AsFd,
216     data: EventData,
217     event_flags: EventFlags,
218 ) -> io::Result<()> {
219     let raw_fd = source.as_fd().as_raw_fd();
220 
221     // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
222     // behaves. We use our own `Event` struct instead of libc's because
223     // ours preserves pointer provenance instead of just using a `u64`,
224     // and we have tests elsewhere for layout equivalence.
225     unsafe {
226         ret(c::epoll_ctl(
227             epoll.as_fd().as_raw_fd(),
228             c::EPOLL_CTL_MOD,
229             raw_fd,
230             as_mut_ptr(&mut Event {
231                 flags: event_flags,
232                 data,
233                 #[cfg(target_os = "redox")]
234                 _pad: 0,
235             })
236             .cast(),
237         ))
238     }
239 }
240 
241 /// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in a
242 /// given epoll object.
243 #[doc(alias = "epoll_ctl")]
delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()>244 pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
245     // SAFETY: We're calling `epoll_ctl` via FFI and we know how it
246     // behaves.
247     unsafe {
248         let raw_fd = source.as_fd().as_raw_fd();
249         ret(c::epoll_ctl(
250             epoll.as_fd().as_raw_fd(),
251             c::EPOLL_CTL_DEL,
252             raw_fd,
253             null_mut(),
254         ))
255     }
256 }
257 
258 /// `epoll_wait(self, events, timeout)`—Waits for registered events of
259 /// interest.
260 ///
261 /// For each event of interest, an element is written to `events`. On
262 /// success, this returns the number of written elements.
263 #[cfg(feature = "alloc")]
264 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()>265 pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
266     // SAFETY: We're calling `epoll_wait` via FFI and we know how it
267     // behaves.
268     unsafe {
269         event_list.events.set_len(0);
270         let nfds = ret_u32(c::epoll_wait(
271             epoll.as_fd().as_raw_fd(),
272             event_list.events.as_mut_ptr().cast::<c::epoll_event>(),
273             event_list.events.capacity().try_into().unwrap_or(i32::MAX),
274             timeout,
275         ))?;
276         event_list.events.set_len(nfds as usize);
277     }
278 
279     Ok(())
280 }
281 
282 /// An iterator over the `Event`s in an `EventVec`.
283 pub struct Iter<'a> {
284     /// Use `Copied` to copy the struct, since `Event` is `packed` on some
285     /// platforms, and it's common for users to directly destructure it, which
286     /// would lead to errors about forming references to packed fields.
287     iter: core::iter::Copied<slice::Iter<'a, Event>>,
288 }
289 
290 impl<'a> Iterator for Iter<'a> {
291     type Item = Event;
292 
293     #[inline]
next(&mut self) -> Option<Self::Item>294     fn next(&mut self) -> Option<Self::Item> {
295         self.iter.next()
296     }
297 }
298 
299 /// A record of an event that occurred.
300 #[repr(C)]
301 #[cfg_attr(
302     all(
303         linux_kernel,
304         any(
305             all(
306                 target_arch = "x86",
307                 not(target_env = "musl"),
308                 not(target_os = "android"),
309             ),
310             target_arch = "x86_64",
311         )
312     ),
313     repr(packed)
314 )]
315 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
316 pub struct Event {
317     /// Which specific event(s) occurred.
318     pub flags: EventFlags,
319     /// User data.
320     pub data: EventData,
321 
322     #[cfg(target_os = "redox")]
323     _pad: u64,
324 }
325 
326 /// Data associated with an [`Event`]. This can either be a 64-bit integer
327 /// value or a pointer which preserves pointer provenance.
328 #[repr(C)]
329 #[derive(Copy, Clone)]
330 pub union EventData {
331     /// A 64-bit integer value.
332     as_u64: u64,
333 
334     /// A `*mut c_void` which preserves pointer provenance, extended to be
335     /// 64-bit so that if we read the value as a `u64` union field, we don't
336     /// get uninitialized memory.
337     sixty_four_bit_pointer: SixtyFourBitPointer,
338 }
339 
340 impl EventData {
341     /// Construct a new value containing a `u64`.
342     #[inline]
new_u64(value: u64) -> Self343     pub const fn new_u64(value: u64) -> Self {
344         Self { as_u64: value }
345     }
346 
347     /// Construct a new value containing a `*mut c_void`.
348     #[inline]
new_ptr(value: *mut c_void) -> Self349     pub const fn new_ptr(value: *mut c_void) -> Self {
350         Self {
351             sixty_four_bit_pointer: SixtyFourBitPointer {
352                 pointer: value,
353                 #[cfg(target_pointer_width = "32")]
354                 _padding: 0,
355             },
356         }
357     }
358 
359     /// Return the value as a `u64`.
360     ///
361     /// If the stored value was a pointer, the pointer is zero-extended to a
362     /// `u64`.
363     #[inline]
u64(self) -> u64364     pub fn u64(self) -> u64 {
365         unsafe { self.as_u64 }
366     }
367 
368     /// Return the value as a `*mut c_void`.
369     ///
370     /// If the stored value was a `u64`, the least-significant bits of the
371     /// `u64` are returned as a pointer value.
372     #[inline]
ptr(self) -> *mut c_void373     pub fn ptr(self) -> *mut c_void {
374         unsafe { self.sixty_four_bit_pointer.pointer }
375     }
376 }
377 
378 impl PartialEq for EventData {
379     #[inline]
eq(&self, other: &Self) -> bool380     fn eq(&self, other: &Self) -> bool {
381         self.u64() == other.u64()
382     }
383 }
384 
385 impl Eq for EventData {}
386 
387 impl Hash for EventData {
388     #[inline]
hash<H: Hasher>(&self, state: &mut H)389     fn hash<H: Hasher>(&self, state: &mut H) {
390         self.u64().hash(state)
391     }
392 }
393 
394 #[repr(C)]
395 #[derive(Copy, Clone)]
396 struct SixtyFourBitPointer {
397     #[cfg(target_endian = "big")]
398     #[cfg(target_pointer_width = "32")]
399     _padding: u32,
400 
401     pointer: *mut c_void,
402 
403     #[cfg(target_endian = "little")]
404     #[cfg(target_pointer_width = "32")]
405     _padding: u32,
406 }
407 
408 /// A vector of `Event`s, plus context for interpreting them.
409 #[cfg(feature = "alloc")]
410 pub struct EventVec {
411     events: Vec<Event>,
412 }
413 
414 #[cfg(feature = "alloc")]
415 impl EventVec {
416     /// Constructs an `EventVec` from raw pointer, length, and capacity.
417     ///
418     /// # Safety
419     ///
420     /// This function calls [`Vec::from_raw_parts`] with its arguments.
421     ///
422     /// [`Vec::from_raw_parts`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_raw_parts
423     #[inline]
from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self424     pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self {
425         Self {
426             events: Vec::from_raw_parts(ptr, len, capacity),
427         }
428     }
429 
430     /// Constructs an `EventVec` with memory for `capacity` `Event`s.
431     #[inline]
with_capacity(capacity: usize) -> Self432     pub fn with_capacity(capacity: usize) -> Self {
433         Self {
434             events: Vec::with_capacity(capacity),
435         }
436     }
437 
438     /// Returns the current `Event` capacity of this `EventVec`.
439     #[inline]
capacity(&self) -> usize440     pub fn capacity(&self) -> usize {
441         self.events.capacity()
442     }
443 
444     /// Reserves enough memory for at least `additional` more `Event`s.
445     #[inline]
reserve(&mut self, additional: usize)446     pub fn reserve(&mut self, additional: usize) {
447         self.events.reserve(additional);
448     }
449 
450     /// Reserves enough memory for exactly `additional` more `Event`s.
451     #[inline]
reserve_exact(&mut self, additional: usize)452     pub fn reserve_exact(&mut self, additional: usize) {
453         self.events.reserve_exact(additional);
454     }
455 
456     /// Clears all the `Events` out of this `EventVec`.
457     #[inline]
clear(&mut self)458     pub fn clear(&mut self) {
459         self.events.clear();
460     }
461 
462     /// Shrinks the capacity of this `EventVec` as much as possible.
463     #[inline]
shrink_to_fit(&mut self)464     pub fn shrink_to_fit(&mut self) {
465         self.events.shrink_to_fit();
466     }
467 
468     /// Returns an iterator over the `Event`s in this `EventVec`.
469     #[inline]
iter(&self) -> Iter<'_>470     pub fn iter(&self) -> Iter<'_> {
471         Iter {
472             iter: self.events.iter().copied(),
473         }
474     }
475 
476     /// Returns the number of `Event`s logically contained in this `EventVec`.
477     #[inline]
len(&mut self) -> usize478     pub fn len(&mut self) -> usize {
479         self.events.len()
480     }
481 
482     /// Tests whether this `EventVec` is logically empty.
483     #[inline]
is_empty(&mut self) -> bool484     pub fn is_empty(&mut self) -> bool {
485         self.events.is_empty()
486     }
487 }
488 
489 #[cfg(feature = "alloc")]
490 impl<'a> IntoIterator for &'a EventVec {
491     type IntoIter = Iter<'a>;
492     type Item = Event;
493 
494     #[inline]
into_iter(self) -> Self::IntoIter495     fn into_iter(self) -> Self::IntoIter {
496         self.iter()
497     }
498 }
499 
500 #[test]
test_epoll_layouts()501 fn test_epoll_layouts() {
502     check_renamed_type!(Event, epoll_event);
503     check_renamed_type!(Event, epoll_event);
504     check_renamed_struct_renamed_field!(Event, epoll_event, flags, events);
505     check_renamed_struct_renamed_field!(Event, epoll_event, data, u64);
506 }
507