1pub use crate::fd::{Event, Fd, Token};
13
14use crate::CoreError;
15use crate::error::syscall_ret;
16use std::io::Error as IoError;
17use std::os::unix::io::RawFd;
18
19#[inline(always)]
20fn errno() -> i32 {
21 IoError::last_os_error().raw_os_error().unwrap_or(0)
22}
23
24pub struct Reactor {
60 epfd: RawFd,
61 next_token: u64,
62 events_buf: Vec<libc::epoll_event>,
63 signalfd: Option<Fd>,
64 signalfd_previous_mask: Option<libc::sigset_t>,
65 sigchld_token: Option<Token>,
67 inotify_token: Option<Token>,
69}
70
71impl Reactor {
72 pub fn new() -> Result<Self, CoreError> {
79 let epfd = unsafe { libc::epoll_create1(libc::EPOLL_CLOEXEC) };
80 syscall_ret(epfd, "epoll_create1")?;
81 Ok(Self {
82 epfd,
83 next_token: 1,
84 events_buf: Vec::with_capacity(64),
85 signalfd: None,
86 signalfd_previous_mask: None,
87 sigchld_token: None,
88 inotify_token: None,
89 })
90 }
91
92 pub fn setup_inotify(&mut self) -> Result<(Fd, Token), CoreError> {
100 let fd = unsafe { libc::inotify_init1(libc::IN_CLOEXEC | libc::IN_NONBLOCK) };
101 syscall_ret(fd, "inotify_init1")?;
102
103 let fd_obj = Fd::new(fd, "inotify")?;
104 let token = self.add(&fd_obj, true, false)?;
105 self.inotify_token = Some(token);
106
107 Ok((fd_obj, token))
108 }
109
110 pub fn setup_signalfd(&mut self) -> Result<Token, CoreError> {
120 if self.signalfd.is_some() {
121 return Err(CoreError::sys(
122 libc::EINVAL,
123 "setup_signalfd already initialized",
124 ));
125 }
126
127 let mut mask: libc::sigset_t = unsafe { std::mem::zeroed() };
128 unsafe { libc::sigemptyset(&mut mask) };
129 unsafe { libc::sigaddset(&mut mask, libc::SIGCHLD) };
130
131 let mut previous_mask: libc::sigset_t = unsafe { std::mem::zeroed() };
132 let r = unsafe { libc::pthread_sigmask(libc::SIG_BLOCK, &mask, &mut previous_mask) };
133 if r != 0 {
134 return Err(CoreError::sys(r, "pthread_sigmask(SIG_BLOCK)"));
135 }
136
137 let sfd = unsafe { libc::signalfd(-1, &mask, libc::SFD_NONBLOCK | libc::SFD_CLOEXEC) };
138 if let Err(err) = syscall_ret(sfd, "signalfd") {
139 let _ = unsafe {
140 libc::pthread_sigmask(libc::SIG_SETMASK, &previous_mask, std::ptr::null_mut())
141 };
142 return Err(err);
143 }
144
145 let fd = Fd::new(sfd, "signalfd")?;
146 let token = match self.add(&fd, true, false) {
147 Ok(token) => token,
148 Err(err) => {
149 let _ = unsafe {
150 libc::pthread_sigmask(libc::SIG_SETMASK, &previous_mask, std::ptr::null_mut())
151 };
152 return Err(err);
153 }
154 };
155
156 self.signalfd = Some(fd);
157 self.signalfd_previous_mask = Some(previous_mask);
158 self.sigchld_token = Some(token);
159
160 Ok(token)
161 }
162
163 pub fn drain_signalfd(&self) -> Result<(), CoreError> {
165 if let Some(fd) = &self.signalfd {
166 let mut buf = [0u8; std::mem::size_of::<libc::signalfd_siginfo>()];
167 loop {
168 match fd.read_slice(&mut buf) {
169 Ok(Some(n)) if n < buf.len() => break,
170 Ok(Some(_)) => continue,
171 Ok(None) => break,
172 Err(e) => return Err(e),
173 }
174 }
175 }
176 Ok(())
177 }
178
179 #[inline(always)]
184 pub fn add(&mut self, fd: &Fd, readable: bool, writable: bool) -> Result<Token, CoreError> {
185 let token = Token(self.next_token);
186 self.next_token += 1;
187 self.add_with_token(fd.raw(), token, readable, writable, false)?;
188 Ok(token)
189 }
190
191 #[inline(always)]
193 pub fn add_priority(&mut self, fd: &Fd) -> Result<Token, CoreError> {
194 let token = Token(self.next_token);
195 self.next_token += 1;
196 self.add_with_token(fd.raw(), token, false, false, true)?;
197 Ok(token)
198 }
199
200 #[inline(always)]
213 pub fn add_with_flags(&mut self, fd: &Fd, flags: u32) -> Result<Token, CoreError> {
214 let token = Token(self.next_token);
215 self.next_token += 1;
216 let mut ev = libc::epoll_event {
217 events: flags,
218 u64: token.0,
219 };
220 let r = unsafe { libc::epoll_ctl(self.epfd, libc::EPOLL_CTL_ADD, fd.raw(), &mut ev) };
221 syscall_ret(r, "epoll_ctl_add")?;
222 Ok(token)
223 }
224
225 #[inline(always)]
226 pub(crate) fn add_with_token(
227 &mut self,
228 raw_fd: RawFd,
229 token: Token,
230 readable: bool,
231 writable: bool,
232 priority: bool,
233 ) -> Result<(), CoreError> {
234 let mut events = libc::EPOLLET as u32;
235 if readable {
236 events |= libc::EPOLLIN as u32;
237 }
238 if writable {
239 events |= libc::EPOLLOUT as u32;
240 }
241 if priority {
242 events |= libc::EPOLLPRI as u32;
243 }
244 let mut ev = libc::epoll_event {
245 events,
246 u64: token.0,
247 };
248 let r = unsafe { libc::epoll_ctl(self.epfd, libc::EPOLL_CTL_ADD, raw_fd, &mut ev) };
249 syscall_ret(r, "epoll_ctl_add")?;
250 Ok(())
251 }
252
253 #[inline(always)]
255 pub fn del(&self, fd: &Fd) -> Result<(), CoreError> {
256 self.del_raw(fd.raw())
257 }
258
259 #[inline(always)]
264 pub(crate) fn del_raw(&self, raw: RawFd) -> Result<(), CoreError> {
265 loop {
266 let ret = unsafe {
267 libc::epoll_ctl(self.epfd, libc::EPOLL_CTL_DEL, raw, std::ptr::null_mut())
268 };
269 if ret == -1 {
270 let e = errno();
271 if e == libc::EINTR {
272 continue;
273 }
274 return Err(CoreError::sys(e, "epoll_ctl_del"));
275 }
276 return Ok(());
277 }
278 }
279
280 #[inline(always)]
292 pub fn wait(
293 &mut self,
294 buffer: &mut Vec<Event>,
295 max_events: usize,
296 timeout: i32,
297 ) -> Result<usize, CoreError> {
298 buffer.clear();
299
300 if max_events == 0 {
301 return Ok(0);
302 }
303
304 if buffer.capacity() < max_events {
306 buffer.reserve(max_events.saturating_sub(buffer.len()));
307 }
308
309 if self.events_buf.capacity() < max_events {
310 self.events_buf
311 .reserve(max_events.saturating_sub(self.events_buf.len()));
312 }
313
314 let n = unsafe {
315 libc::epoll_wait(
316 self.epfd,
317 self.events_buf.as_mut_ptr(),
318 max_events as i32,
319 timeout,
320 )
321 };
322
323 if n > 0 {
324 unsafe {
325 self.events_buf.set_len(n as usize);
326 }
327 for i in 0..n as usize {
328 let ev = self.events_buf[i];
329 let is_read = (ev.events & libc::EPOLLIN as u32) != 0;
330 let is_priority = (ev.events & libc::EPOLLPRI as u32) != 0;
331 let is_write = (ev.events & libc::EPOLLOUT as u32) != 0;
332 let is_err = (ev.events & libc::EPOLLERR as u32) != 0;
333 let is_hup = (ev.events & libc::EPOLLHUP as u32) != 0;
334
335 buffer.push(Event {
336 token: Token(ev.u64),
337 readable: is_read || is_err,
338 priority: is_priority || is_err,
339 writable: is_write || is_err,
340 error: is_err,
341 hangup: is_hup,
342 });
343 }
344 return Ok(n as usize);
345 }
346
347 if n < 0 {
348 let e = errno();
349 if e == libc::EINTR {
350 return Ok(0);
351 }
352 return Err(CoreError::sys(e, "epoll_wait"));
353 }
354 Ok(0)
355 }
356
357 #[allow(dead_code)]
361 pub(crate) fn fd(&self) -> RawFd {
362 self.epfd
363 }
364}
365
366impl Drop for Reactor {
367 fn drop(&mut self) {
368 if let Some(mask) = self.signalfd_previous_mask.take() {
369 let _ =
370 unsafe { libc::pthread_sigmask(libc::SIG_SETMASK, &mask, std::ptr::null_mut()) };
371 }
372 if self.epfd >= 0 {
373 unsafe {
374 libc::close(self.epfd);
375 }
376 }
377 }
378}