Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SignalFd::set_mask #2141

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fixed the function signature of `recvmmsg`, potentially causing UB
([#2119](https://github.com/nix-rust/nix/issues/2119))

- Fix `SignalFd::set_mask`. In 0.27.0 it would actually close the file
descriptor.
([#2141](https://github.com/nix-rust/nix/pull/2141))

### Changed

- The following APIs now take an implementation of `AsFd` rather than a
Expand Down
13 changes: 12 additions & 1 deletion src/sys/signalfd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl SignalFd {
}

pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
_signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop)
self.update(mask, SfdFlags::empty())
}

pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
Expand All @@ -119,6 +119,17 @@ impl SignalFd {
Err(error) => Err(error),
}
}

fn update(&self, mask: &SigSet, flags: SfdFlags) -> Result<()> {
let raw_fd = self.0.as_raw_fd();
unsafe {
Errno::result(libc::signalfd(
raw_fd,
mask.as_ref(),
flags.bits(),
)).map(drop)
}
}
}

impl AsFd for SignalFd {
Expand Down
29 changes: 29 additions & 0 deletions test/sys/test_signalfd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,32 @@ fn test_signalfd() {
let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
assert_eq!(signo, signal::SIGUSR1);
}

/// Update the signal mask of an already existing signalfd.
#[test]
fn test_signalfd_setmask() {
use nix::sys::signal::{self, raise, SigSet, Signal};
use nix::sys::signalfd::SignalFd;

// Grab the mutex for altering signals so we don't interfere with other tests.
let _m = crate::SIGNAL_MTX.lock();

// Block the SIGUSR1 signal from automatic processing for this thread
let mut mask = SigSet::empty();

let mut fd = SignalFd::new(&mask).unwrap();

mask.add(signal::SIGUSR1);
mask.thread_block().unwrap();
fd.set_mask(&mask).unwrap();

// Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
// because `kill` with `getpid` isn't correct during multi-threaded execution like during a
// cargo test session. Instead use `raise` which does the correct thing by default.
raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");

// And now catch that same signal.
let res = fd.read_signal().unwrap().unwrap();
let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
assert_eq!(signo, signal::SIGUSR1);
}