route_manager/unix/
shutdown.rs1use crate::RouteListener;
2use std::io;
3use std::os::fd::AsRawFd;
4use std::sync::atomic::{AtomicBool, Ordering};
5use std::sync::Arc;
6
7struct EventFd(libc::c_int, libc::c_int);
8impl EventFd {
9 fn new() -> io::Result<Self> {
10 let mut fds: [libc::c_int; 2] = [0; 2];
11 if unsafe { libc::pipe(fds.as_mut_ptr()) } == -1 {
12 return Err(io::Error::last_os_error());
13 }
14 let read_fd = fds[0];
15 let write_fd = fds[1];
16 Ok(Self(read_fd, write_fd))
17 }
18 fn wake(&self) -> io::Result<()> {
19 let buf: [u8; 8] = 1u64.to_ne_bytes();
20 let res = unsafe { libc::write(self.1, buf.as_ptr() as *const libc::c_void, buf.len()) };
21 if res == -1 {
22 Err(io::Error::last_os_error())
23 } else {
24 Ok(())
25 }
26 }
27 fn as_event_fd(&self) -> libc::c_int {
28 self.0
29 }
30}
31impl Drop for EventFd {
32 fn drop(&mut self) {
33 unsafe {
34 let _ = libc::close(self.0);
35 let _ = libc::close(self.1);
36 }
37 }
38}
39impl RouteListener {
40 pub(crate) fn wait(&self) -> io::Result<()> {
41 let fd = self.as_raw_fd() as libc::c_int;
42
43 let event_fd = self.shutdown_handle.event_fd.as_event_fd();
44 let mut readfds: libc::fd_set = unsafe { std::mem::zeroed() };
45 unsafe {
46 libc::FD_SET(fd, &mut readfds);
47 libc::FD_SET(event_fd, &mut readfds);
48 }
49 let result = unsafe {
50 libc::select(
51 fd.max(event_fd) + 1,
52 &mut readfds,
53 std::ptr::null_mut(),
54 std::ptr::null_mut(),
55 std::ptr::null_mut(),
56 )
57 };
58 if self.shutdown_handle.is_shutdown.load(Ordering::Relaxed) {
59 return Err(io::Error::new(io::ErrorKind::Interrupted, "shutdown"));
60 }
61 if result == -1 {
62 return Err(io::Error::last_os_error());
63 }
64 if result == 0 {
65 return Err(io::Error::from(io::ErrorKind::TimedOut));
66 }
67 Ok(())
68 }
69 pub fn shutdown_handle(&self) -> io::Result<RouteListenerShutdown> {
71 Ok(self.shutdown_handle.clone())
72 }
73}
74
75#[derive(Clone)]
77pub struct RouteListenerShutdown {
78 is_shutdown: Arc<AtomicBool>,
79 event_fd: Arc<EventFd>,
80}
81impl RouteListenerShutdown {
82 pub(crate) fn new() -> io::Result<Self> {
83 Ok(Self {
84 is_shutdown: Arc::new(Default::default()),
85 event_fd: Arc::new(EventFd::new()?),
86 })
87 }
88 pub fn shutdown(&self) -> io::Result<()> {
90 self.is_shutdown.store(true, Ordering::Relaxed);
91 self.event_fd.wake()
92 }
93}