1 | #[cfg (not(target_os = "redox" ))] |
2 | use nix::errno::Errno; |
3 | use nix::sys::signal::*; |
4 | use nix::unistd::*; |
5 | use std::convert::TryFrom; |
6 | use std::sync::atomic::{AtomicBool, Ordering}; |
7 | |
8 | #[test] |
9 | fn test_kill_none() { |
10 | kill(getpid(), None).expect("Should be able to send signal to myself." ); |
11 | } |
12 | |
13 | #[test] |
14 | #[cfg (not(target_os = "fuchsia" ))] |
15 | fn test_killpg_none() { |
16 | killpg(getpgrp(), None) |
17 | .expect("Should be able to send signal to my process group." ); |
18 | } |
19 | |
20 | #[test] |
21 | fn test_old_sigaction_flags() { |
22 | let _m = crate::SIGNAL_MTX.lock(); |
23 | |
24 | extern "C" fn handler(_: ::libc::c_int) {} |
25 | let act = SigAction::new( |
26 | SigHandler::Handler(handler), |
27 | SaFlags::empty(), |
28 | SigSet::empty(), |
29 | ); |
30 | let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); |
31 | let _flags = oact.flags(); |
32 | let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); |
33 | let _flags = oact.flags(); |
34 | } |
35 | |
36 | #[test] |
37 | fn test_sigprocmask_noop() { |
38 | sigprocmask(SigmaskHow::SIG_BLOCK, None, None) |
39 | .expect("this should be an effective noop" ); |
40 | } |
41 | |
42 | #[test] |
43 | fn test_sigprocmask() { |
44 | let _m = crate::SIGNAL_MTX.lock(); |
45 | |
46 | // This needs to be a signal that rust doesn't use in the test harness. |
47 | const SIGNAL: Signal = Signal::SIGCHLD; |
48 | |
49 | let mut old_signal_set = SigSet::empty(); |
50 | sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) |
51 | .expect("expect to be able to retrieve old signals" ); |
52 | |
53 | // Make sure the old set doesn't contain the signal, otherwise the following |
54 | // test don't make sense. |
55 | assert!( |
56 | !old_signal_set.contains(SIGNAL), |
57 | "the {SIGNAL:?} signal is already blocked, please change to a \ |
58 | different one" |
59 | ); |
60 | |
61 | // Now block the signal. |
62 | let mut signal_set = SigSet::empty(); |
63 | signal_set.add(SIGNAL); |
64 | sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None) |
65 | .expect("expect to be able to block signals" ); |
66 | |
67 | // And test it again, to make sure the change was effective. |
68 | old_signal_set.clear(); |
69 | sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) |
70 | .expect("expect to be able to retrieve old signals" ); |
71 | assert!( |
72 | old_signal_set.contains(SIGNAL), |
73 | "expected the {SIGNAL:?} to be blocked" |
74 | ); |
75 | |
76 | // Reset the signal. |
77 | sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None) |
78 | .expect("expect to be able to block signals" ); |
79 | } |
80 | |
81 | static SIGNALED: AtomicBool = AtomicBool::new(false); |
82 | |
83 | extern "C" fn test_sigaction_handler(signal: libc::c_int) { |
84 | let signal = Signal::try_from(signal).unwrap(); |
85 | SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed); |
86 | } |
87 | |
88 | #[cfg (not(target_os = "redox" ))] |
89 | extern "C" fn test_sigaction_action( |
90 | _: libc::c_int, |
91 | _: *mut libc::siginfo_t, |
92 | _: *mut libc::c_void, |
93 | ) { |
94 | } |
95 | |
96 | #[test] |
97 | #[cfg (not(target_os = "redox" ))] |
98 | fn test_signal_sigaction() { |
99 | let _m = crate::SIGNAL_MTX.lock(); |
100 | |
101 | let action_handler = SigHandler::SigAction(test_sigaction_action); |
102 | assert_eq!( |
103 | unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), |
104 | Errno::ENOTSUP |
105 | ); |
106 | } |
107 | |
108 | #[test] |
109 | fn test_signal() { |
110 | let _m = crate::SIGNAL_MTX.lock(); |
111 | |
112 | unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap(); |
113 | raise(Signal::SIGINT).unwrap(); |
114 | assert_eq!( |
115 | unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), |
116 | SigHandler::SigIgn |
117 | ); |
118 | |
119 | let handler = SigHandler::Handler(test_sigaction_handler); |
120 | assert_eq!( |
121 | unsafe { signal(Signal::SIGINT, handler) }.unwrap(), |
122 | SigHandler::SigDfl |
123 | ); |
124 | raise(Signal::SIGINT).unwrap(); |
125 | assert!(SIGNALED.load(Ordering::Relaxed)); |
126 | |
127 | #[cfg (not(any(target_os = "illumos" , target_os = "solaris" )))] |
128 | assert_eq!( |
129 | unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), |
130 | handler |
131 | ); |
132 | |
133 | // System V based OSes (e.g. illumos and Solaris) always resets the |
134 | // disposition to SIG_DFL prior to calling the signal handler |
135 | #[cfg (any(target_os = "illumos" , target_os = "solaris" ))] |
136 | assert_eq!( |
137 | unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), |
138 | SigHandler::SigDfl |
139 | ); |
140 | |
141 | // Restore default signal handler |
142 | unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); |
143 | } |
144 | |