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

macos: add signal shim for downstream rust-vmm crates#268

Closed
christhomas wants to merge 1 commit into
rust-vmm:mainfrom
christhomas:cth/macos
Closed

macos: add signal shim for downstream rust-vmm crates#268
christhomas wants to merge 1 commit into
rust-vmm:mainfrom
christhomas:cth/macos

Conversation

@christhomas

@christhomas christhomas commented May 15, 2026

Copy link
Copy Markdown

Summary

Adds macOS support for the signal module so downstream rust-vmm crates can install process-lifecycle signal handlers (register_signal_handler, block_signal, Killable, etc.) on macOS the same way they do on Linux today. 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 — everything in this PR is original work.

Why this is needed

vmm-sys-util already provides a Linux signal module that wraps the POSIX sigaction/sigprocmask/sigpending machinery and exposes typed helpers used across the rust-vmm ecosystem. Without an equivalent on macOS, any consumer that uses those helpers fails to compile on macOS — there is no vmm_sys_util::signal::* for the cfg resolver to find.

Concrete real-world consumer: virtiofsd installs a clean-exit handler for SIGHUP and SIGTERM so the process tears down its vhost-user socket cleanly when the controlling terminal closes or systemd stops it:

// virtiofsd src/main.rs
fn set_signal_handlers() {
    use vmm_sys_util::signal;
    extern "C" fn handle_signal(_: c_int, _: *mut siginfo_t, _: *mut c_void) {
        unsafe { libc::_exit(1) };
    }
    for s in [libc::SIGHUP, libc::SIGTERM] {
        signal::register_signal_handler(s, handle_signal)?;
    }
}

The wrapper isn't doing anything magical — it could be written against raw libc::sigaction — but using vmm_sys_util::signal here gets the same validation (validate_signal_num), the same error-handling shape, and the same Killable abstraction that the rest of the rust-vmm ecosystem uses. Having one consistent API makes consumers portable across platforms with no #[cfg] at the call site.

Why this code lives in vmm-sys-util

Symmetric placement: the Linux signal module already lives in vmm-sys-util as src/linux/signal.rs. Putting the macOS equivalent under src/macos/signal.rs keeps "POSIX signal helpers for rust-vmm" in one crate instead of splitting it across crates by platform. Anyone who later wants to bring another rust-vmm crate to macOS gets the same API for free.

The shim is also self-contained: ~400 lines, its own unit tests, no new dependencies on the crate. Linux/Android builds don't see it at all.

(If maintainers would prefer to keep vmm-sys-util Linux-only and push macOS shims into the downstream consumers that need them, that's also reasonable and I'm happy to take the code elsewhere. Wanted to flag the option.)

What's in it

  • src/macos/signal.rs — POSIX signal helpers mirroring the Linux module's public API.
    • Host-signal validation uses 1..=SIGUSR2 because macOS signal numbers do not match Linux's (SIGSYS=12, SIGTERM=15, SIGUSR2=31). The SIGHUP..=SIGSYS range used on Linux would reject valid macOS signals.
    • Pending-signal clearing goes via unblock-then-reblock because macOS does not expose sigtimedwait.

What's not in it (and why)

This PR deliberately omits eventfd and epoll shims that an earlier draft of this branch included, after upstream discussion on #266.

  • No eventfd shim. The cross-platform EventConsumer / EventNotifier primitive added in Implement EventNotifier/EventConsumer as a generic event notification #244 already covers the daemon side of vhost-user-backend. The remaining macOS callers of vmm_sys_util::eventfd::EventFd are inside the vhost crate's VhostBackend / VhostBackendMut traits, whose only consumers are Linux-only (kernel vhost drivers, vhost-user frontends inside Linux-only VMMs). A small follow-up PR to vhost gates those trait methods on #[cfg(target_os = \"linux\")], after which nothing in the macOS build path references vmm_sys_util::eventfd and a shim is genuinely unnecessary.

  • No epoll shim. Consumers needing epoll-shaped polling on macOS should use mio (see Use mio to replace Epoll vhost#316), which gives proper cross-platform event polling backed by kqueue on macOS — a cleaner architectural answer than shimming the Linux API.

The previous version of this branch carried both shims, adapted from libkrun, which required dual-licensing the crate as BSD-3-Clause AND Apache-2.0. Dropping those shims removes the libkrun derivation entirely; the crate stays single-licensed BSD-3-Clause.

End-to-end validation

The signal-only version of this PR + rust-vmm/vhost#316 (mio rewrite) + the VhostBackend cfg-gating follow-up was tested on aarch64-apple-darwin: virtiofsd → vhost-user-backendvhostvmm-sys-util builds clean and 75/75 virtiofsd lib tests pass.

Tests

  • macos::signal::tests — validator range, register/block/unblock/kill round-trips, pending-signal clearing.

There are 4 pre-existing test failures in rand and unix::tempdir on macOS that this PR does not introduce or fix; they are out of scope.

Checklist

  • All commits in this PR have `Signed-off-by` trailers, subject ≤ 60 chars and body lines ≤ 75 chars.
  • All added/changed functionality has a corresponding unit test.
  • All added/changed public-facing functionality has entries in the "Upcoming Release" section of CHANGELOG.md.
  • Any newly added unsafe code is properly documented.

@stefano-garzarella

Copy link
Copy Markdown
Member

This is something similar to #266, same comments apply here...

@christhomas

Copy link
Copy Markdown
Author

ah damn you're right and I also saw his pull request on the virtiofsd gitlab repo but I never saw the PR here.

So, what I get from this, is that eventfs is already covered by EventNotifier from PR 244 and epoll you're wanting to replace it with mio?

If you think this is the direction you'll go, i'll move the PR in that direction, but I see that the mio PR 316 is still open and not merged but I realise it's gotten a lot of action recently, so I guess this is the way to go?

Adds macOS compatibility for the `signal` module so downstream rust-vmm
crates (`vhost`, `vhost-user-backend`, `virtiofsd`, …) 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.

Host-signal validation uses `1..=SIGUSR2` because macOS signal numbers
do not match Linux's: SIGSYS=12, SIGTERM=15, SIGUSR2=31. The
`SIGHUP..=SIGSYS` range used on Linux would reject valid macOS signals.
Pending-signal clearing goes via unblock-then-reblock because macOS
does not expose `sigtimedwait`.

What this PR no longer ships, and why:

- No `eventfd` shim. The cross-platform `EventConsumer` /
  `EventNotifier` primitive added in rust-vmm#244 already covers the daemon
  side of `vhost-user-backend`. The remaining macOS callers of
  `vmm_sys_util::eventfd::EventFd` are inside the `vhost` crate's
  `VhostBackend` / `VhostBackendMut` traits, whose only consumers are
  Linux-only (kernel vhost drivers, vhost-user frontends inside
  Linux-only VMMs). A small follow-up PR to `vhost` gates those trait
  methods on Linux, after which nothing in the macOS build path
  references `vmm_sys_util::eventfd` and a shim is genuinely
  unnecessary.

- No `epoll` shim. Consumers needing epoll-shaped polling on macOS
  should use `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::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>
christhomas added a commit to christhomas/vhost that referenced this pull request May 15, 2026
The `VhostBackend` and `VhostBackendMut` traits in `vhost/src/backend.rs`
take `&EventFd` in `set_vring_call`, `set_vring_kick`, and
`set_vring_err`. The implementations of these traits are all Linux-only
consumers — kernel vhost drivers (`vhost_kern/`, gated on the
`vhost-kern` feature) and the vhost-user frontend (gated on
`vhost-user-frontend`). No macOS consumer ever calls these methods.

Until now, the unconditional `use vmm_sys_util::eventfd::EventFd;` at
the top of `backend.rs` forced every dependent crate (including
`vhost-user-backend` consumers like virtiofsd) to compile against
`vmm_sys_util::eventfd` even when nothing in the build path called these
methods. On macOS that meant requiring an `eventfd` shim inside
vmm-sys-util just for the type to resolve.

Gate the import, the six trait method signatures, the corresponding
methods in `impl<T: VhostBackendMut> VhostBackend for {RwLock,RefCell}<T>`,
and the test mock + test on `#[cfg(target_os = "linux")]`. The trait
becomes a smaller surface on macOS — exactly the surface that has
working consumers there. Linux behaviour is unchanged.

This unblocks dropping the macOS `eventfd` shim from vmm-sys-util
(rust-vmm/vmm-sys-util#268), and combined with the mio rewrite of
`vhost-user-backend`'s event loop (rust-vmm#316), removes the last hard
dependency between the macOS build path and `vmm_sys_util::eventfd`.

Tested: full virtiofsd → vhost-user-backend → vhost → vmm-sys-util
stack builds and tests pass on aarch64-apple-darwin with no eventfd
shim in vmm-sys-util.

Signed-off-by: Chris Thomas <chris.thomas@antimatter-studios.com>
@andreeaflorescu

Copy link
Copy Markdown
Member

Side note, unrelated to the change, we're moving the vmm-sys-util repository to the mono repo. We're hoping to get this done by the end of the week (2026-05-22). We'll want to merge this in the new repository. Since it's currently not done, I think we can continue the review here, and just move it for the merge there? WDYT?

@christhomas christhomas changed the title Add macOS shims for eventfd, epoll, and signal modules macos: add signal shim for downstream rust-vmm crates May 18, 2026
@christhomas

christhomas commented May 18, 2026

Copy link
Copy Markdown
Author

I updated the pull request to reflect the changes we discussed over the last days. I've tested on my machine using qemu on my macbook and I am happy so far, I don't see any issues with this locally

@christhomas

Copy link
Copy Markdown
Author

Side note, unrelated to the change, we're moving the vmm-sys-util repository to the mono repo. We're hoping to get this done by the end of the week (2026-05-22). We'll want to merge this in the new repository. Since it's currently not done, I think we can continue the review here, and just move it for the merge there? WDYT?

Yeah, so we leave this here and I'll rebase it onto the new version when its done. Sounds good

@stefano-garzarella

Copy link
Copy Markdown
Member

ah damn you're right and I also saw his pull request on the virtiofsd gitlab repo but I never saw the PR here.

Don't worry :-)

So, what I get from this, is that eventfs is already covered by EventNotifier from PR 244 and epoll you're wanting to replace it with mio?

Right!

If you think this is the direction you'll go, i'll move the PR in that direction, but I see that the mio PR 316 is still open and not merged but I realise it's gotten a lot of action recently, so I guess this is the way to go?

Yeah, we should go in that direction IMO.

@stefano-garzarella

Copy link
Copy Markdown
Member

I updated the pull request to reflect the changes we discussed over the last days. I've tested on my machine using qemu on my macbook and I am happy so far, I don't see any issues with this locally

How this is related with #263 ?

@andreeaflorescu

Copy link
Copy Markdown
Member

We finished the merging of vmm-sys-util to rust-vmm, can you please move the PR 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