Skip to content

Commit abd72be

Browse files
committed
Merge #826
826: Add sigprocmask r=asomers a=Thomasdezeeuw
2 parents bb69c29 + efc9ac3 commit abd72be

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5050
([#741](https://github.com/nix-rust/nix/pull/741))
5151
- Added more standard trait implementations for various types.
5252
([#814](https://github.com/nix-rust/nix/pull/814))
53+
- Added `sigprocmask` to the signal module.
54+
([#826](https://github.com/nix-rust/nix/pull/826))
5355

5456
### Changed
5557
- Use native `pipe2` on all BSD targets. Users should notice no difference.

src/sys/signal.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,27 @@ pub fn pthread_sigmask(how: SigmaskHow,
445445
Errno::result(res).map(drop)
446446
}
447447

448+
/// Examine and change blocked signals.
449+
///
450+
/// For more informations see the [`sigprocmask` man
451+
/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
452+
pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
453+
if set.is_none() && oldset.is_none() {
454+
return Ok(())
455+
}
456+
457+
let res = unsafe {
458+
// if set or oldset is None, pass in null pointers instead
459+
libc::sigprocmask(how as libc::c_int,
460+
set.map_or_else(ptr::null::<libc::sigset_t>,
461+
|s| &s.sigset as *const libc::sigset_t),
462+
oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
463+
|os| &mut os.sigset as *mut libc::sigset_t))
464+
};
465+
466+
Errno::result(res).map(drop)
467+
}
468+
448469
pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
449470
let res = unsafe { libc::kill(pid.into(),
450471
match signal.into() {

test/sys/test_signal.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,45 @@ use nix::sys::signal::*;
55
fn test_kill_none() {
66
kill(getpid(), None).expect("Should be able to send signal to myself.");
77
}
8+
9+
#[test]
10+
fn test_sigprocmask_noop() {
11+
sigprocmask(SigmaskHow::SIG_BLOCK, None, None)
12+
.expect("this should be an effective noop");
13+
}
14+
15+
#[test]
16+
fn test_sigprocmask() {
17+
#[allow(unused_variables)]
18+
let m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
19+
20+
// This needs to be a signal that rust doesn't use in the test harness.
21+
const SIGNAL: Signal = Signal::SIGCHLD;
22+
23+
let mut old_signal_set = SigSet::empty();
24+
sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
25+
.expect("expect to be able to retrieve old signals");
26+
27+
// Make sure the old set doesn't contain the signal, otherwise the following
28+
// test don't make sense.
29+
assert_eq!(old_signal_set.contains(SIGNAL), false,
30+
"the {:?} signal is already blocked, please change to a \
31+
different one", SIGNAL);
32+
33+
// Now block the signal.
34+
let mut signal_set = SigSet::empty();
35+
signal_set.add(SIGNAL);
36+
sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None)
37+
.expect("expect to be able to block signals");
38+
39+
// And test it again, to make sure the change was effective.
40+
old_signal_set.clear();
41+
sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
42+
.expect("expect to be able to retrieve old signals");
43+
assert_eq!(old_signal_set.contains(SIGNAL), true,
44+
"expected the {:?} to be blocked", SIGNAL);
45+
46+
// Reset the signal.
47+
sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
48+
.expect("expect to be able to block signals");
49+
}

0 commit comments

Comments
 (0)