notifier_macos.rs92.16%
1
// Copyright 2025 Google LLC2
//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 at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// 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 and13
// limitations under the License.14
15
use std::fs::File;16
use std::io::{ErrorKind, Result};17
use std::os::fd::{FromRawFd, OwnedFd};18
use std::os::unix::io::AsRawFd;19
use std::ptr::{null, null_mut};20
21
use mio::event::Source;22
use mio::{Interest, Registry, Token};23
24
use crate::ffi;25
26
#[derive(Debug)]27
pub struct Notifier {28
fd: OwnedFd,29
registered: Option<(Token, OwnedFd)>,30
}31
32
impl Notifier {33
pub fn new() -> Result<Self> {4x34
Ok(Notifier {35
fd: File::open("/dev/null")?.into(),4x36
registered: None,4x37
})38
}4x39
40
pub fn notify(&self) -> Result<()> {15x41
let Some((token, kqfd)) = &self.registered else {15x42
return Err(ErrorKind::NotFound.into());43
};44
let event = libc::kevent {15x45
ident: self.fd.as_raw_fd() as _,15x46
filter: libc::EVFILT_USER,15x47
flags: libc::EV_ADD | libc::EV_RECEIPT,15x48
fflags: libc::NOTE_TRIGGER,15x49
data: 0,15x50
udata: token.0 as _,15x51
};15x52
ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;15x53
Ok(())15x54
}15x55
}56
57
impl Source for Notifier {58
fn register(&mut self, registry: &Registry, token: Token, _: Interest) -> Result<()> {4x59
let event = libc::kevent {4x60
ident: self.fd.as_raw_fd() as _,4x61
filter: libc::EVFILT_USER,4x62
flags: libc::EV_ADD | libc::EV_CLEAR | libc::EV_RECEIPT,4x63
fflags: 0,4x64
data: 0,4x65
udata: null_mut(),4x66
};4x67
68
let kqfd = registry.as_raw_fd();4x69
let kqfd = ffi!(unsafe { libc::dup(kqfd) })?;4x70
let kqfd = unsafe { OwnedFd::from_raw_fd(kqfd) };4x71
72
ffi!(unsafe { libc::kevent(kqfd.as_raw_fd(), &event, 1, null_mut(), 0, null()) })?;4x73
self.registered = Some((token, kqfd));4x74
Ok(())4x75
}4x76
77
fn deregister(&mut self, registry: &Registry) -> Result<()> {2x78
let event = libc::kevent {2x79
ident: self.fd.as_raw_fd() as _,2x80
filter: libc::EVFILT_USER,2x81
flags: libc::EV_DELETE | libc::EV_RECEIPT,2x82
fflags: 0,2x83
data: 0,2x84
udata: null_mut(),2x85
};2x86
87
let kqfd = registry.as_raw_fd();2x88
89
ffi!(unsafe { libc::kevent(kqfd, &event, 1, null_mut(), 0, null()) })?;2x90
self.registered = None;2x91
Ok(())2x92
}2x93
94
fn reregister(&mut self, _: &Registry, _: Token, _: Interest) -> Result<()> {95
Err(ErrorKind::Unsupported.into())96
}97
}98