summaryrefslogtreecommitdiff
path: root/vendor/rustix/src/kernel_sigset.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
committermo khan <mo@mokhan.ca>2025-07-02 18:36:06 -0600
commit8cdfa445d6629ffef4cb84967ff7017654045bc2 (patch)
tree22f0b0907c024c78d26a731e2e1f5219407d8102 /vendor/rustix/src/kernel_sigset.rs
parent4351c74c7c5f97156bc94d3a8549b9940ac80e3f (diff)
chore: add vendor directory
Diffstat (limited to 'vendor/rustix/src/kernel_sigset.rs')
-rw-r--r--vendor/rustix/src/kernel_sigset.rs326
1 files changed, 326 insertions, 0 deletions
diff --git a/vendor/rustix/src/kernel_sigset.rs b/vendor/rustix/src/kernel_sigset.rs
new file mode 100644
index 00000000..706bcb8c
--- /dev/null
+++ b/vendor/rustix/src/kernel_sigset.rs
@@ -0,0 +1,326 @@
+//! The [`KernelSigSet`] type.
+
+#![allow(unsafe_code)]
+#![allow(non_camel_case_types)]
+
+use crate::backend::c;
+use crate::signal::Signal;
+use core::fmt;
+use linux_raw_sys::general::{kernel_sigset_t, _NSIG};
+
+/// `kernel_sigset_t`—A set of signal numbers, as used by some syscalls.
+///
+/// This is similar to `libc::sigset_t`, but with only enough space for the
+/// signals currently known to be used by the kernel. libc implementations
+/// reserve extra space so that if Linux defines new signals in the future
+/// they can add support without breaking their dynamic linking ABI. Rustix
+/// doesn't support a dynamic linking ABI, so if we need to increase the
+/// size of `KernelSigSet` in the future, we can do so.
+///
+/// It's also the case that the last time Linux changed the size of its
+/// `kernel_sigset_t` was when it added support for POSIX.1b signals in 1999.
+///
+/// `KernelSigSet` is guaranteed to have a subset of the layout of
+/// `libc::sigset_t`.
+///
+/// libc implementations typically also reserve some signal values for internal
+/// use. In a process that contains a libc, some unsafe functions invoke
+/// undefined behavior if passed a `KernelSigSet` that contains one of the
+/// signals that the libc reserves.
+#[repr(transparent)]
+#[derive(Clone)]
+pub struct KernelSigSet(kernel_sigset_t);
+
+impl KernelSigSet {
+ /// Create a new empty `KernelSigSet`.
+ pub const fn empty() -> Self {
+ const fn zeros<const N: usize>() -> [c::c_ulong; N] {
+ [0; N]
+ }
+ Self(kernel_sigset_t { sig: zeros() })
+ }
+
+ /// Create a new `KernelSigSet` with all signals set.
+ ///
+ /// This includes signals which are typically reserved for libc.
+ pub const fn all() -> Self {
+ const fn ones<const N: usize>() -> [c::c_ulong; N] {
+ [!0; N]
+ }
+ Self(kernel_sigset_t { sig: ones() })
+ }
+
+ /// Remove all signals.
+ pub fn clear(&mut self) {
+ *self = Self(kernel_sigset_t {
+ sig: Default::default(),
+ });
+ }
+
+ /// Insert a signal.
+ pub fn insert(&mut self, sig: Signal) {
+ let sigs_per_elt = core::mem::size_of_val(&self.0.sig[0]) * 8;
+
+ let raw = (sig.as_raw().wrapping_sub(1)) as usize;
+ self.0.sig[raw / sigs_per_elt] |= 1 << (raw % sigs_per_elt);
+ }
+
+ /// Insert all signals.
+ pub fn insert_all(&mut self) {
+ self.0.sig.fill(!0);
+ }
+
+ /// Remove a signal.
+ pub fn remove(&mut self, sig: Signal) {
+ let sigs_per_elt = core::mem::size_of_val(&self.0.sig[0]) * 8;
+
+ let raw = (sig.as_raw().wrapping_sub(1)) as usize;
+ self.0.sig[raw / sigs_per_elt] &= !(1 << (raw % sigs_per_elt));
+ }
+
+ /// Test whether a given signal is present.
+ pub fn contains(&self, sig: Signal) -> bool {
+ let sigs_per_elt = core::mem::size_of_val(&self.0.sig[0]) * 8;
+
+ let raw = (sig.as_raw().wrapping_sub(1)) as usize;
+ (self.0.sig[raw / sigs_per_elt] & (1 << (raw % sigs_per_elt))) != 0
+ }
+}
+
+impl Default for KernelSigSet {
+ #[inline]
+ fn default() -> Self {
+ Self::empty()
+ }
+}
+
+impl fmt::Debug for KernelSigSet {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut d = f.debug_set();
+
+ // Surprisingly, `_NSIG` is inclusive.
+ for i in 1..=_NSIG {
+ // SAFETY: This value is non-zero, in range, and only used for
+ // debug output.
+ let sig = unsafe { Signal::from_raw_unchecked(i as _) };
+
+ if self.contains(sig) {
+ d.entry(&sig);
+ }
+ }
+
+ d.finish()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[cfg(linux_raw)]
+ use crate::runtime::{KERNEL_SIGRTMAX, KERNEL_SIGRTMIN};
+ use core::mem::{align_of, size_of};
+
+ #[test]
+ fn test_assumptions() {
+ #[cfg(linux_raw)]
+ assert!(KERNEL_SIGRTMAX as usize - 1 < size_of::<KernelSigSet>() * 8);
+ }
+
+ #[test]
+ fn test_layouts() {
+ assert!(size_of::<KernelSigSet>() <= size_of::<libc::sigset_t>());
+ assert!(align_of::<KernelSigSet>() <= align_of::<libc::sigset_t>());
+ }
+
+ /// A bunch of signals for testing.
+ fn sigs() -> Vec<Signal> {
+ #[allow(unused_mut)]
+ let mut sigs = vec![
+ Signal::HUP,
+ Signal::INT,
+ Signal::QUIT,
+ Signal::ILL,
+ Signal::TRAP,
+ Signal::ABORT,
+ Signal::BUS,
+ Signal::FPE,
+ Signal::KILL,
+ Signal::USR1,
+ Signal::SEGV,
+ Signal::USR2,
+ Signal::PIPE,
+ Signal::ALARM,
+ Signal::TERM,
+ Signal::CHILD,
+ Signal::CONT,
+ Signal::STOP,
+ Signal::TSTP,
+ Signal::TTIN,
+ Signal::TTOU,
+ Signal::URG,
+ Signal::XCPU,
+ Signal::XFSZ,
+ Signal::VTALARM,
+ Signal::PROF,
+ Signal::WINCH,
+ Signal::SYS,
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMIN()) },
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMIN() + 7) },
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMAX()) },
+ ];
+
+ #[cfg(linux_raw)]
+ {
+ sigs.push(unsafe { Signal::from_raw_unchecked(KERNEL_SIGRTMIN) });
+ sigs.push(unsafe { Signal::from_raw_unchecked(KERNEL_SIGRTMIN + 7) });
+ sigs.push(unsafe { Signal::from_raw_unchecked(KERNEL_SIGRTMAX) });
+ }
+
+ sigs
+ }
+
+ /// A bunch of non-reserved signals for testing.
+ fn libc_sigs() -> [Signal; 31] {
+ [
+ Signal::HUP,
+ Signal::INT,
+ Signal::QUIT,
+ Signal::ILL,
+ Signal::TRAP,
+ Signal::ABORT,
+ Signal::BUS,
+ Signal::FPE,
+ Signal::KILL,
+ Signal::USR1,
+ Signal::SEGV,
+ Signal::USR2,
+ Signal::PIPE,
+ Signal::ALARM,
+ Signal::TERM,
+ Signal::CHILD,
+ Signal::CONT,
+ Signal::STOP,
+ Signal::TSTP,
+ Signal::TTIN,
+ Signal::TTOU,
+ Signal::URG,
+ Signal::XCPU,
+ Signal::XFSZ,
+ Signal::VTALARM,
+ Signal::PROF,
+ Signal::WINCH,
+ Signal::SYS,
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMIN()) },
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMIN() + 7) },
+ unsafe { Signal::from_raw_unchecked(libc::SIGRTMAX()) },
+ ]
+ }
+
+ #[test]
+ fn test_ops_plain() {
+ for sig in sigs() {
+ let mut set = KernelSigSet::empty();
+ for sig in sigs() {
+ assert!(!set.contains(sig));
+ }
+
+ set.insert(sig);
+ assert!(set.contains(sig));
+ for sig in sigs().iter().filter(|s| **s != sig) {
+ assert!(!set.contains(*sig));
+ }
+
+ set.remove(sig);
+ for sig in sigs() {
+ assert!(!set.contains(sig));
+ }
+ }
+ }
+
+ #[test]
+ fn test_clear() {
+ let mut set = KernelSigSet::empty();
+ for sig in sigs() {
+ set.insert(sig);
+ }
+
+ set.clear();
+
+ for sig in sigs() {
+ assert!(!set.contains(sig));
+ }
+ }
+
+ // io_uring libraries assume that libc's `sigset_t` matches the layout
+ // of the Linux kernel's `kernel_sigset_t`. Test that rustix's layout
+ // matches as well.
+ #[test]
+ fn test_libc_layout_compatibility() {
+ use crate::utils::as_ptr;
+
+ let mut lc = unsafe { core::mem::zeroed::<libc::sigset_t>() };
+ let mut ru = KernelSigSet::empty();
+ let r = unsafe { libc::sigemptyset(&mut lc) };
+
+ assert_eq!(r, 0);
+ assert_eq!(
+ unsafe {
+ libc::memcmp(
+ as_ptr(&lc).cast(),
+ as_ptr(&ru).cast(),
+ core::mem::size_of::<KernelSigSet>(),
+ )
+ },
+ 0
+ );
+
+ for sig in libc_sigs() {
+ ru.insert(sig);
+ assert_ne!(
+ unsafe {
+ libc::memcmp(
+ as_ptr(&lc).cast(),
+ as_ptr(&ru).cast(),
+ core::mem::size_of::<KernelSigSet>(),
+ )
+ },
+ 0
+ );
+ let r = unsafe { libc::sigaddset(&mut lc, sig.as_raw()) };
+ assert_eq!(r, 0);
+ assert_eq!(
+ unsafe {
+ libc::memcmp(
+ as_ptr(&lc).cast(),
+ as_ptr(&ru).cast(),
+ core::mem::size_of::<KernelSigSet>(),
+ )
+ },
+ 0
+ );
+ ru.remove(sig);
+ assert_ne!(
+ unsafe {
+ libc::memcmp(
+ as_ptr(&lc).cast(),
+ as_ptr(&ru).cast(),
+ core::mem::size_of::<KernelSigSet>(),
+ )
+ },
+ 0
+ );
+ let r = unsafe { libc::sigdelset(&mut lc, sig.as_raw()) };
+ assert_eq!(r, 0);
+ assert_eq!(
+ unsafe {
+ libc::memcmp(
+ as_ptr(&lc).cast(),
+ as_ptr(&ru).cast(),
+ core::mem::size_of::<KernelSigSet>(),
+ )
+ },
+ 0
+ );
+ }
+ }
+}