usecrate::backend::c; usecrate::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)] pubstruct KernelSigSet(kernel_sigset_t);
/// Create a new `KernelSigSet` with all signals set. /// /// This includes signals which are typically reserved for libc. pubconstfn all() -> Self { constfn ones<const N: usize>() -> [c::c_ulong; N] {
[!0; N]
} Self(kernel_sigset_t { sig: ones() })
}
/// Insert a signal. pubfn insert(&mutself, 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. pubfn insert_all(&mutself) { self.0.sig.fill(!0);
}
/// Remove a signal. pubfn remove(&mutself, 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. pubfn 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 fmt::Debug for KernelSigSet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { letmut d = f.debug_set();
// Surprisingly, `_NSIG` is inclusive. for i in1..=_NSIG { // SAFETY: This value is non-zero, in range, and only used for // debug output. let sig = unsafe { Signal::from_raw_unchecked(i as _) };
ifself.contains(sig) {
d.entry(&sig);
}
}
d.finish()
}
}
#[cfg(test)] mod tests { usesuper::*; #[cfg(linux_raw)] usecrate::runtime::{KERNEL_SIGRTMAX, KERNEL_SIGRTMIN}; use core::mem::{align_of, size_of};
#[test] fn test_ops_plain() { for sig in sigs() { letmut 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() { letmut 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() { usecrate::utils::as_ptr;
letmut lc = unsafe { core::mem::zeroed::<libc::sigset_t>() }; letmut ru = KernelSigSet::empty(); let r = unsafe { libc::sigemptyset(&mut lc) };
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.