diff --git a/src/backend/libc/event/syscalls.rs b/src/backend/libc/event/syscalls.rs index def689ebd..5beaed161 100644 --- a/src/backend/libc/event/syscalls.rs +++ b/src/backend/libc/event/syscalls.rs @@ -314,9 +314,13 @@ pub(crate) fn port_getn( events: &mut Vec, mut nget: u32, ) -> io::Result<()> { + // `port_getn` special-cases a max value of 0 to be a query that returns + // the number of events. We don't want to do the `set_len` in that case, so + // so bail out early if needed. if events.capacity() == 0 { return Ok(()); } + let timeout = timeout.map_or(null_mut(), as_mut_ptr); unsafe { ret(c::port_getn( @@ -336,6 +340,24 @@ pub(crate) fn port_getn( Ok(()) } +#[cfg(solarish)] +pub(crate) fn port_getn_query(port: BorrowedFd<'_>) -> io::Result { + let mut nget: u32 = 0; + + // Pass a `max` of 0 to query the number of available events. + unsafe { + ret(c::port_getn( + borrowed_fd(port), + null_mut(), + 0, + &mut nget, + null_mut(), + ))?; + } + + Ok(nget) +} + #[cfg(solarish)] pub(crate) fn port_send( port: BorrowedFd<'_>, diff --git a/src/event/port.rs b/src/event/port.rs index 39fe5ac16..094618317 100644 --- a/src/event/port.rs +++ b/src/event/port.rs @@ -110,6 +110,13 @@ pub fn port_get(port: impl AsFd, timeout: Option) -> io::Result /// `port_getn(port, events, min_events, timeout)`—Gets multiple events from a /// port. /// +/// This requests up to a max of `events.capacity()` events, and then resizes +/// `events` to the number of events retrieved. If `events.capacity()` is 0, +/// this does nothing and returns immediately. +/// +/// To query the number of events without retrieving any, use +/// [`port_getn_query`]. +/// /// # References /// - [OpenSolaris] /// - [illumos] @@ -138,6 +145,21 @@ pub fn port_getn( ) } +/// `port_getn(port, NULL, 0, NULL)`—Queries the number of events +/// available from a port. +/// +/// To retrieve the events, use [`port_getn`]. +/// +/// # References +/// - [OpenSolaris] +/// - [illumos] +/// +/// [OpenSolaris]: https://www.unix.com/man-page/opensolaris/3C/port_getn/ +/// [illumos]: https://illumos.org/man/3C/port_getn +pub fn port_getn_query(port: impl AsFd) -> io::Result { + syscalls::port_getn_query(port.as_fd()) +} + /// `port_send(port, events, userdata)`—Sends an event to a port. /// /// # References