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> {12x
34 Ok(Notifier {
35 fd: File::open("/dev/null")?.into(),12x
36 registered: None,12x
37 })
38 }12x
39
40 pub fn notify(&self) -> Result<()> {21x
41 let Some((token, kqfd)) = &self.registered else {21x
42 return Err(ErrorKind::NotFound.into());
43 };
44 let event = libc::kevent {21x
45 ident: self.fd.as_raw_fd() as _,21x
46 filter: libc::EVFILT_USER,21x
47 flags: libc::EV_ADD | libc::EV_RECEIPT,21x
48 fflags: libc::NOTE_TRIGGER,21x
49 data: 0,21x
50 udata: token.0 as _,21x
51 };21x
52 ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;21x
53 Ok(())21x
54 }21x
55}
56
57impl Source for Notifier {
58 fn register(&mut self, registry: &Registry, token: Token, _: Interest) -> Result<()> {12x
59 let event = libc::kevent {12x
60 ident: self.fd.as_raw_fd() as _,12x
61 filter: libc::EVFILT_USER,12x
62 flags: libc::EV_ADD | libc::EV_CLEAR | libc::EV_RECEIPT,12x
63 fflags: 0,12x
64 data: 0,12x
65 udata: null_mut(),12x
66 };12x
67
68 let kqfd = registry.as_raw_fd();12x
69 let kqfd = ffi!(unsafe { libc::dup(kqfd) })?;12x
70 let kqfd = unsafe { OwnedFd::from_raw_fd(kqfd) };12x
71
72 ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;12x
73 self.registered = Some((token, kqfd));12x
74 Ok(())12x
75 }12x
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