Alioth Code Coverage

notifier_macos.rs92.16%

1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fs::File;
16use std::io::{ErrorKind, Result};
17use std::os::fd::{FromRawFd, OwnedFd};
18use std::os::unix::io::AsRawFd;
19use std::ptr::{null, null_mut};
20
21use mio::event::Source;
22use mio::{Interest, Registry, Token};
23
24use crate::ffi;
25
26#[derive(Debug)]
27pub struct Notifier {
28 fd: OwnedFd,
29 registered: Option<(Token, OwnedFd)>,
30}
31
32impl Notifier {
33 pub fn new() -> Result<Self> {24x
34 Ok(Notifier {
35 fd: File::open("/dev/null")?.into(),24x
36 registered: None,24x
37 })
38 }24x
39
40 pub fn notify(&self) -> Result<()> {29x
41 let Some((token, kqfd)) = &self.registered else {29x
42 return Err(ErrorKind::NotFound.into());
43 };
44 let event = libc::kevent {29x
45 ident: self.fd.as_raw_fd() as _,29x
46 filter: libc::EVFILT_USER,29x
47 flags: libc::EV_ADD | libc::EV_RECEIPT,29x
48 fflags: libc::NOTE_TRIGGER,29x
49 data: 0,29x
50 udata: token.0 as _,29x
51 };29x
52 ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;29x
53 Ok(())29x
54 }29x
55}
56
57impl Source for Notifier {
58 fn register(&mut self, registry: &Registry, token: Token, _: Interest) -> Result<()> {24x
59 let event = libc::kevent {24x
60 ident: self.fd.as_raw_fd() as _,24x
61 filter: libc::EVFILT_USER,24x
62 flags: libc::EV_ADD | libc::EV_CLEAR | libc::EV_RECEIPT,24x
63 fflags: 0,24x
64 data: 0,24x
65 udata: null_mut(),24x
66 };24x
67
68 let kqfd = registry.as_raw_fd();24x
69 let kqfd = ffi!(unsafe { libc::dup(kqfd) })?;24x
70 let kqfd = unsafe { OwnedFd::from_raw_fd(kqfd) };24x
71
72 ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;24x
73 self.registered = Some((token, kqfd));24x
74 Ok(())24x
75 }24x
76
77 fn deregister(&mut self, registry: &Registry) -> Result<()> {2x
78 let event = libc::kevent {2x
79 ident: self.fd.as_raw_fd() as _,2x
80 filter: libc::EVFILT_USER,2x
81 flags: libc::EV_DELETE | libc::EV_RECEIPT,2x
82 fflags: 0,2x
83 data: 0,2x
84 udata: null_mut(),2x
85 };2x
86
87 let kqfd = registry.as_raw_fd();2x
88
89 ffi!(unsafe { libc::kevent(kqfd, &event, 1, null_mut(), 0, null()) })?;2x
90 self.registered = None;2x
91 Ok(())2x
92 }2x
93
94 fn reregister(&mut self, _: &Registry, _: Token, _: Interest) -> Result<()> {
95 Err(ErrorKind::Unsupported.into())
96 }
97}
98