From 7f6a587a3cc1ce3df5378d247021cf4a4f672488 Mon Sep 17 00:00:00 2001 From: German Maglione Date: Wed, 8 Jun 2022 15:55:13 +0200 Subject: [PATCH] SigSet: A new unsafe helper method to create a SigSet from a sigset_t Currently, the only way to create a `SigSet` from a `sigset_t` object is by using pointer casts, like: ``` unsafe { let sigset = *(&sigset as *const libc::sigset_t as *const SigSet) }; ``` This is un-ergonomic for library creators with interfaces to C. So, let's add a new unsafe method that creates a `SigSet` from a `libc::sigset_t` object. We can't implement `From` since converting from `libc::sigset_t` to `SigSet` is unsafe, because objects of type `libc::sigset_t` must be initialized by calling either `sigemptyset(3)` or `sigfillset(3)` before being used. In other case, the results are undefined. We can't implement `TryFrom` either, because there is no way to check if an object of type `libc::sigset_t` is initialized. Signed-off-by: German Maglione --- CHANGELOG.md | 2 ++ src/sys/signal.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f40e4089f..7b31cd1316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). (#[1703](https://github.com/nix-rust/nix/pull/1703)) - Added `ptrace::read_user` and `ptrace::write_user` for Linux. (#[1697](https://github.com/nix-rust/nix/pull/1697)) +- Added `from_sigset_t_unchecked()` to `signal::SigSet`. + (#[1741](https://github.com/nix-rust/nix/pull/1741)) ### Changed diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 9a4e90e4ce..a039201fb7 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -619,6 +619,15 @@ impl SigSet { Signal::try_from(signum.assume_init()).unwrap() }) } + + /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking whether the `libc::sigset_t` + /// is already initialized. Objects of type`libc::sigset_t` must be initialized by calling either + /// [`sigemptyset(3)`](https://man7.org/linux/man-pages/man3/sigemptyset.3p.html) or + /// [`sigfillset(3)`](https://man7.org/linux/man-pages/man3/sigfillset.3p.html) + /// before being used. In other case, the results are undefined. + pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet { + SigSet { sigset } + } } impl AsRef for SigSet { @@ -1344,4 +1353,22 @@ mod tests { assert_eq!(mask.wait().unwrap(), SIGUSR1); }).join().unwrap(); } + + #[test] + fn test_from_sigset_t_unchecked() { + let src_set = SigSet::empty(); + let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) }; + + for signal in Signal::iterator() { + assert!(!set.contains(signal)); + } + + let src_set = SigSet::all(); + let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) }; + + for signal in Signal::iterator() { + assert!(set.contains(signal)); + } + } + }