From e83418e0bb65e72eaa36bbb72b7fceedd8d31fe1 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 4 Jun 2022 08:30:50 -0600 Subject: [PATCH] Allow setting kevent_flags on struct sigevent Also, disallow using SigevNotify::SigevThreadId on musl. I don't think it ever worked. Depends on https://github.com/rust-lang/libc/pull/2813 Blocks https://github.com/tokio-rs/tokio/issues/4728 --- Cargo.toml | 2 +- src/sys/signal.rs | 106 +++++++++++++++++++++++++--------------------- 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 65b4b9aed1..611c38eae2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.126", features = [ "extra_traits" ] } +libc = { git = "https://github.com/asomers/libc.git", rev = "c95acde3ffa5f333efd0a7d49139b6b738935c6b", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" pin-utils = { version = "0.1.0", optional = true } diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 9a4e90e4ce..19e5a8bd85 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -1029,8 +1029,7 @@ pub enum SigevNotify { /// structure of the queued signal. si_value: libc::intptr_t }, - // Note: SIGEV_THREAD is not implemented because libc::sigevent does not - // expose a way to set the union members needed by SIGEV_THREAD. + // Note: SIGEV_THREAD is not implemented, but could be if desired. /// Notify by delivering an event to a kqueue. #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] #[cfg_attr(docsrs, doc(cfg(all())))] @@ -1040,8 +1039,24 @@ pub enum SigevNotify { /// Will be contained in the kevent's `udata` field. udata: libc::intptr_t }, + /// Notify by delivering an event to a kqueue, with optional event flags set + #[cfg(target_os = "freebsd")] + #[cfg_attr(docsrs, doc(cfg(all())))] + #[cfg(feature = "event")] + SigevKeventFlags { + /// File descriptor of the kqueue to notify. + kq: RawFd, + /// Will be contained in the kevent's `udata` field. + udata: libc::intptr_t, + /// Flags that will be set on the delivered event. See `kevent(2)`. + flags: crate::sys::event::EventFlag + }, /// Notify by delivering a signal to a thread. - #[cfg(any(target_os = "freebsd", target_os = "linux"))] + #[cfg(any( + target_os = "freebsd", + target_env = "gnu", + target_env = "uclibc", + ))] #[cfg_attr(docsrs, doc(cfg(all())))] SigevThreadId { /// Signal to send @@ -1062,10 +1077,7 @@ mod sigevent { #![any(feature = "aio", feature = "signal")] use std::mem; - use std::ptr; use super::SigevNotify; - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - use super::type_of_thread_id; /// Used to request asynchronous notification of the completion of certain /// events, such as POSIX AIO and timers. @@ -1093,53 +1105,51 @@ mod sigevent { // See https://github.com/nix-rust/nix/issues/1441 #[cfg_attr(target_os = "fuchsia", allow(invalid_value))] pub fn new(sigev_notify: SigevNotify) -> SigEvent { - let mut sev = unsafe { mem::MaybeUninit::::zeroed().assume_init() }; - sev.sigev_notify = match sigev_notify { - SigevNotify::SigevNone => libc::SIGEV_NONE, - SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL, + let mut sev: libc::sigevent = unsafe { mem::zeroed() }; + match sigev_notify { + SigevNotify::SigevNone => { + sev.sigev_notify = libc::SIGEV_NONE; + }, + SigevNotify::SigevSignal{signal, si_value} => { + sev.sigev_notify = libc::SIGEV_SIGNAL; + sev.sigev_signo = signal as libc::c_int; + sev.sigev_value.sival_ptr = si_value as *mut libc::c_void + }, #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT, + SigevNotify::SigevKevent{kq, udata} => { + sev.sigev_notify = libc::SIGEV_KEVENT; + sev.sigev_signo = kq; + sev.sigev_value.sival_ptr = udata as *mut libc::c_void; + }, #[cfg(target_os = "freebsd")] - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, - #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))] - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, - #[cfg(all(target_os = "linux", target_env = "uclibc"))] - SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID, - #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))] - SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined - }; - sev.sigev_signo = match sigev_notify { - SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{ kq, ..} => kq, - #[cfg(any(target_os = "linux", target_os = "freebsd"))] - SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int, - _ => 0 - }; - sev.sigev_value.sival_ptr = match sigev_notify { - SigevNotify::SigevNone => ptr::null_mut::(), - SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void, - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void, - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void, - }; - SigEvent::set_tid(&mut sev, &sigev_notify); + #[cfg(feature = "event")] + SigevNotify::SigevKeventFlags{kq, udata, flags} => { + sev.sigev_notify = libc::SIGEV_KEVENT; + sev.sigev_signo = kq; + sev.sigev_value.sival_ptr = udata as *mut libc::c_void; + sev._sigev_un._kevent_flags = flags.bits(); + }, + #[cfg(target_os = "freebsd")] + SigevNotify::SigevThreadId{signal, thread_id, si_value} => { + sev.sigev_notify = libc::SIGEV_THREAD_ID; + sev.sigev_signo = signal as libc::c_int; + sev.sigev_value.sival_ptr = si_value as *mut libc::c_void; + sev._sigev_un._threadid = thread_id; + } + #[cfg(any( + target_env = "gnu", + target_env = "uclibc", + ))] + SigevNotify::SigevThreadId{signal, thread_id, si_value} => { + sev.sigev_notify = libc::SIGEV_THREAD_ID; + sev.sigev_signo = signal as libc::c_int; + sev.sigev_value.sival_ptr = si_value as *mut libc::c_void; + sev._sigev_un._tid = thread_id; + } + } SigEvent{sigevent: sev} } - #[cfg(any(target_os = "freebsd", target_os = "linux"))] - fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) { - sev.sigev_notify_thread_id = match *sigev_notify { - SigevNotify::SigevThreadId { thread_id, .. } => thread_id, - _ => 0 as type_of_thread_id - }; - } - - #[cfg(not(any(target_os = "freebsd", target_os = "linux")))] - fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) { - } - /// Return a copy of the inner structure pub fn sigevent(&self) -> libc::sigevent { self.sigevent