Skip to content
This repository was archived by the owner on May 22, 2026. It is now read-only.

macos: add epoll and eventfd compatibility shims#266

Closed
mheese wants to merge 1 commit into
rust-vmm:mainfrom
mheese:macos-epoll-eventfd-shims
Closed

macos: add epoll and eventfd compatibility shims#266
mheese wants to merge 1 commit into
rust-vmm:mainfrom
mheese:macos-epoll-eventfd-shims

Conversation

@mheese

@mheese mheese commented Apr 17, 2026

Copy link
Copy Markdown

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 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.

Requirements

Before submitting your PR, please make sure you addressed the following
requirements:

  • All commits in this PR have Signed-Off-By trailers (with
    git commit -s), and the commit message has max 60 characters for the
    summary and max 75 characters for each description line.
  • All added/changed functionality has a corresponding unit/integration
    test.
  • All added/changed public-facing functionality has entries in the "Upcoming
    Release" section of CHANGELOG.md (if no such section exists, please create one).
  • Any newly added unsafe code is properly documented.

Notes

  • I understand that this PR might be quite controversial and/or problematic. This takes and adapts the implementation from libkrun. And because of that it requires the licensing changes. If that is not wanted, then somebody needs to write this or something similar from scatch.
  • Furthermore, this emulates epoll and eventfd only 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.
  • This PR is the outcome of a discussion ona virtiofsd issue here: https://gitlab.com/virtio-fs/virtiofsd/-/work_items/169
  • I know that German Maglione said that he would work on this PR I'm opening here right now this week, but it apparently did not happen, so I decided I make a PR with the patch to this crate that I'm currently using myself for my own private (working) macOS virtiofsd implementation.
  • This does not complete full macOS support just yet. While the crate compiles and with these changes the vhost and vhost-user-backend compile 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
  • Also, if I understand the CI repository correctly, the unit tests here would not be running on macOS.

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>
@stefano-garzarella

Copy link
Copy Markdown
Member

We recently introduced EventConsumer and EventNotifier to abstract eventfd (see #244), can we avoid to re-introduce eventfd.rs ?

@stefano-garzarella

Copy link
Copy Markdown
Member

CC @germag

@mheese

mheese commented Apr 20, 2026

Copy link
Copy Markdown
Author

We recently introduced EventConsumer and EventNotifier to abstract eventfd (see #244), can we avoid to re-introduce eventfd.rs ?

absolutely! sorry, I did not see that.

@stefano-garzarella

Copy link
Copy Markdown
Member

@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 mio in vmm-sys-util and use mio directly in the crates.

Do you think this can work for you as well ?

@mheese

mheese commented Apr 22, 2026

Copy link
Copy Markdown
Author

@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 mio in vmm-sys-util and use mio directly in the crates.

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 vhost-user-backend to work under macOS to begin with.

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.

christhomas added a commit to christhomas/vmm-sys-util that referenced this pull request May 15, 2026
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>
@andreeaflorescu

Copy link
Copy Markdown
Member

@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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants