macos: add epoll and eventfd compatibility shims#266
Conversation
Add macOS implementations of the Linux epoll and eventfd APIs so that crates depending on vmm-sys-util (notably vhost-user-backend consumers such as virtiofsd) can compile and run on macOS. epoll is emulated on top of kqueue; eventfd is emulated using a pipe pair. Both modules are adapted from the libkrun project. The sources were taken from the `main` branch of https://github.com/containers/libkrun as of 2026-04-17 (HEAD a3b7ae213195c9f871a17c72f0d020e46ed90584 at the time of adaptation; most recent change to the copied files: commit 9168b0312bb2fb30b50fcfdb1825958a6a30f338 on 2026-03-07): - src/macos/epoll.rs adapted from src/utils/src/macos/epoll.rs - src/macos/eventfd.rs adapted from src/utils/src/macos/eventfd.rs The files retain their original copyright notices (Sergio Lopez, 2021; Amazon.com, Inc., 2020) and their original SPDX identifiers: - epoll.rs: Apache-2.0 - eventfd.rs: Apache-2.0 AND BSD-3-Clause The crate's `license` field in Cargo.toml is updated to `BSD-3-Clause AND Apache-2.0` to reflect the mixed licensing, and a new `LICENSE-Apache-2.0` file is added alongside the existing `LICENSE-BSD-3-Clause`. Local changes relative to the libkrun originals: - Reshape the public surface to match vmm-sys-util's existing Linux epoll/eventfd API (e.g. `EpollEvent` field visibility, `ctl()` taking `EpollEvent` by value, `wait(timeout, events)` signature without a separate `max_events` argument). - eventfd: add `EFD_CLOEXEC` support, implement `FromRawFd` and `IntoRawFd`, and switch from `nix` back to raw `libc` to avoid adding a new dependency. - epoll: add `ONE_SHOT`, `EXCLUSIVE`, `WAKE_UP`, `ERROR` and `PRIORITY` flags, honor the caller-supplied timeout instead of a hardcoded 3-second timespec, drop the `add_oneshot_timer` helper and the `log`-based debug tracing, and return `io::Error` on kevent registration failures instead of asserting. Credit to Sergio Lopez and the libkrun contributors for the original implementations. Signed-off-by: Marcus Heese <mheese@proofpoint.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
We recently introduced EventConsumer and EventNotifier to abstract eventfd (see #244), can we avoid to re-introduce |
|
CC @germag |
absolutely! sorry, I did not see that. |
|
@mheese don't need to apologize at all :-) For the epoll IIRC we are doing something in the vhost crate to use some external crate. See rust-vmm/vhost#316 IIRC last year when @germag and I mentored the GSoC project, we decided to avoid adding another abstraction on top of Do you think this can work for you as well ? |
@stefano-garzarella Yeah, I don't see why this wouldn't work! That is actually way better to begin with. This would mean that both EventFd and Epoll would be "platform independent" (--> at least they should work as-is on macOS), and then this whole PR would be superfluous which is even better! :) The only reason for my patches here were to ge the also @germag I got permission to make the source code for our "macOS virtiofsd" public under my own github org now. So you guys can look at this now here: https://github.com/mheese/macosvirtiofsd . I should have time in the coming days to make a branch and test that against the new eventfd and epoll changes from that PR, and I can report back (here? or somewhere else?) on how this goes. The intention for that repo are for it to be hopefully only temporary until we have macOS support in the main virtiofsd available as well. |
Adds macOS compatibility for `eventfd` and `signal` so downstream rust-vmm crates can build and run on macOS without code changes. All macOS code is gated behind `#[cfg(target_os = "macos")]` and adds no new dependencies; Linux and Android builds are unaffected. The crate stays at `BSD-3-Clause` and no third-party code is vendored. The eventfd shim is a thin wrapper over the cross-platform pipe-backed event primitive added in rust-vmm#244 (`new_event_consumer_and_notifier`). It reuses that primitive's pipe construction and flag handling and drives the raw fds with 8-byte u64 read/write so the value-passing semantics required by the existing tests are preserved. This addresses the direction reviewers have indicated for rust-vmm#266: prefer the cross-platform abstraction over re-introducing Linux-API shims. The signal module is original BSD-3-Clause work. Host-signal validation uses `1..=SIGUSR2` because macOS signal numbers do not match Linux's (SIGSYS=12, SIGTERM=15, SIGUSR2=31), so the `SIGHUP..=SIGSYS` range used on Linux would reject valid macOS signals. No `epoll` shim is provided. Consumers needing epoll-shaped polling on macOS should migrate to `mio` (see vhost #316), which gives proper cross-platform event polling backed by `kqueue` on macOS — a cleaner architectural answer than shimming the Linux API. Tests: - `macos::eventfd::tests` — `test_new`, `test_clone`, `test_read_nothing`, `test_read_write`. All pass. - `macos::signal::tests` — validator range, register/block/unblock/kill round-trips, pending-signal clearing. Pre-existing failures in `rand` and `unix::tempdir` on macOS are out of scope for this PR. Signed-off-by: Chris Thomas <chris.thomas@antimatter-studios.com>
|
@mheese are you still interested in getting this PR merged? If yes, could you please re-open it in https://github.com/rust-vmm/rust-vmm/. We moved vmm-sys-util there. |
Summary of the PR
Add macOS implementations of the Linux epoll and eventfd APIs so that crates depending on vmm-sys-util (notably vhost-user-backend consumers such as virtiofsd) can compile and run on macOS. epoll is emulated on top of kqueue; eventfd is emulated using a pipe pair.
Both modules are adapted from the libkrun project. The sources were taken from the
mainbranch of https://github.com/containers/libkrun as of 2026-04-17 (HEAD a3b7ae213195c9f871a17c72f0d020e46ed90584 at the time of adaptation; most recent change to the copied files: commit 9168b0312bb2fb30b50fcfdb1825958a6a30f338 on 2026-03-07):The files retain their original copyright notices (Sergio Lopez, 2021; Amazon.com, Inc., 2020) and their original SPDX identifiers:
The crate's
licensefield in Cargo.toml is updated toBSD-3-Clause AND Apache-2.0to reflect the mixed licensing, and a newLICENSE-Apache-2.0file is added alongside the existingLICENSE-BSD-3-Clause.Local changes relative to the libkrun originals:
EpollEventfield visibility,ctl()takingEpollEventby value,wait(timeout, events)signature without a separatemax_eventsargument).EFD_CLOEXECsupport, implementFromRawFdandIntoRawFd, and switch fromnixback to rawlibcto avoid adding a new dependency.ONE_SHOT,EXCLUSIVE,WAKE_UP,ERRORandPRIORITYflags, honor the caller-supplied timeout instead of a hardcoded 3-second timespec, drop theadd_oneshot_timerhelper and thelog-based debug tracing, and returnio::Erroron kevent registration failures instead of asserting.Credit to Sergio Lopez and the libkrun contributors for the original implementations.
Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafecode is properly documented.Notes
epollandeventfdonly because vhost-user-backend requires it. Obviously, it would be nicer if that would not be a requirement there to begin with, but would have a more generic interface.vhostandvhost-user-backendcompile on macOS (and seem to work well for me), there are 4x unit tests (unrelated to the functionality in here) which are currently failing. Might be related to this PR here: Enhance rand to support macos #159