Skip to content

Commit e1ad0a3

Browse files
committed
Auto merge of #362 - fiveop:signal_enum, r=posborne
Signal enum This is work in progress. I post this pull request as a request for discussion. I mark the lines I have doubts or ideas about. Ignore the first commit. It is the same as PR #361, which I wanted to base this change off.
2 parents c57de08 + 5c7b3c1 commit e1ad0a3

File tree

2 files changed

+194
-95
lines changed

2 files changed

+194
-95
lines changed

src/sys/signal.rs

+174-75
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,60 @@
22
// See http://rust-lang.org/COPYRIGHT.
33

44
use libc;
5-
use {Errno, Result};
5+
use {Errno, Error, Result};
66
use std::mem;
77
use std::ptr;
88

9-
pub use libc::{
9+
// Currently there is only one definition of c_int in libc, as well as only one
10+
// type for signal constants.
11+
// We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
12+
// this is not (yet) possible.
13+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14+
#[repr(i32)]
15+
pub enum Signal {
16+
SIGHUP = libc::SIGHUP,
17+
SIGINT = libc::SIGINT,
18+
SIGQUIT = libc::SIGQUIT,
19+
SIGILL = libc::SIGILL,
20+
SIGTRAP = libc::SIGTRAP,
21+
SIGABRT = libc::SIGABRT,
22+
SIGBUS = libc::SIGBUS,
23+
SIGFPE = libc::SIGFPE,
24+
SIGKILL = libc::SIGKILL,
25+
SIGUSR1 = libc::SIGUSR1,
26+
SIGSEGV = libc::SIGSEGV,
27+
SIGUSR2 = libc::SIGUSR2,
28+
SIGPIPE = libc::SIGPIPE,
29+
SIGALRM = libc::SIGALRM,
30+
SIGTERM = libc::SIGTERM,
31+
#[cfg(not(target_os = "macos"))]
32+
SIGSTKFLT = libc::SIGSTKFLT,
33+
SIGCHLD = libc::SIGCHLD,
34+
SIGCONT = libc::SIGCONT,
35+
SIGSTOP = libc::SIGSTOP,
36+
SIGTSTP = libc::SIGTSTP,
37+
SIGTTIN = libc::SIGTTIN,
38+
SIGTTOU = libc::SIGTTOU,
39+
SIGURG = libc::SIGURG,
40+
SIGXCPU = libc::SIGXCPU,
41+
SIGXFSZ = libc::SIGXFSZ,
42+
SIGVTALRM = libc::SIGVTALRM,
43+
SIGPROF = libc::SIGPROF,
44+
SIGWINCH = libc::SIGWINCH,
45+
SIGIO = libc::SIGIO,
46+
#[cfg(not(target_os = "macos"))]
47+
SIGPWR = libc::SIGPWR,
48+
SIGSYS = libc::SIGSYS,
49+
#[cfg(target_os = "macos")]
50+
SIGEMT = libc::SIGEMT,
51+
#[cfg(target_os = "macos")]
52+
SIGINFO = libc::SIGINFO,
53+
}
54+
55+
pub use self::Signal::*;
56+
57+
#[cfg(not(target_os = "macos"))]
58+
const SIGNALS: [Signal; 31] = [
1059
SIGHUP,
1160
SIGINT,
1261
SIGQUIT,
@@ -22,6 +71,7 @@ pub use libc::{
2271
SIGPIPE,
2372
SIGALRM,
2473
SIGTERM,
74+
SIGSTKFLT,
2575
SIGCHLD,
2676
SIGCONT,
2777
SIGSTOP,
@@ -35,26 +85,83 @@ pub use libc::{
3585
SIGPROF,
3686
SIGWINCH,
3787
SIGIO,
38-
SIGSYS,
39-
};
40-
88+
SIGPWR,
89+
SIGSYS];
4190
#[cfg(target_os = "macos")]
42-
pub use libc::{
91+
const SIGNALS: [Signal; 31] = [
92+
SIGHUP,
93+
SIGINT,
94+
SIGQUIT,
95+
SIGILL,
96+
SIGTRAP,
97+
SIGABRT,
98+
SIGBUS,
99+
SIGFPE,
100+
SIGKILL,
101+
SIGUSR1,
102+
SIGSEGV,
103+
SIGUSR2,
104+
SIGPIPE,
105+
SIGALRM,
106+
SIGTERM,
107+
SIGCHLD,
108+
SIGCONT,
109+
SIGSTOP,
110+
SIGTSTP,
111+
SIGTTIN,
112+
SIGTTOU,
113+
SIGURG,
114+
SIGXCPU,
115+
SIGXFSZ,
116+
SIGVTALRM,
117+
SIGPROF,
118+
SIGWINCH,
119+
SIGIO,
120+
SIGSYS,
43121
SIGEMT,
44-
SIGINFO,
45-
};
46-
47-
#[cfg(not(target_os = "macos"))]
48-
pub use libc::{
49-
SIGPWR,
50-
SIGSTKFLT,
51-
SIGIOT, // Alias for SIGABRT
52-
SIGPOLL, // Alias for SIGIO
53-
SIGUNUSED, // Alias for 31
54-
};
122+
SIGINFO];
55123

56124
pub const NSIG: libc::c_int = 32;
57125

126+
pub struct SignalIterator {
127+
next: usize,
128+
}
129+
130+
impl Iterator for SignalIterator {
131+
type Item = Signal;
132+
133+
fn next(&mut self) -> Option<Signal> {
134+
if self.next < SIGNALS.len() {
135+
let next_signal = SIGNALS[self.next];
136+
self.next += 1;
137+
Some(next_signal)
138+
} else {
139+
None
140+
}
141+
}
142+
}
143+
144+
impl Signal {
145+
pub fn iterator() -> SignalIterator {
146+
SignalIterator{next: 0}
147+
}
148+
149+
// We do not implement the From trait, because it is supposed to be infallible.
150+
// With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
151+
// implemented, we'll replace this function.
152+
#[inline]
153+
pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
154+
match 0 < signum && signum < NSIG {
155+
true => Ok(unsafe { mem::transmute(signum) }),
156+
false => Err(Error::invalid_argument()),
157+
}
158+
}
159+
}
160+
161+
pub const SIGIOT : Signal = SIGABRT;
162+
pub const SIGPOLL : Signal = SIGIO;
163+
pub const SIGUNUSED : Signal = SIGSYS;
164+
58165
bitflags!{
59166
flags SaFlags: libc::c_int {
60167
const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
@@ -80,7 +187,6 @@ pub struct SigSet {
80187
sigset: libc::sigset_t
81188
}
82189

83-
pub type SigNum = libc::c_int;
84190

85191
impl SigSet {
86192
pub fn all() -> SigSet {
@@ -97,40 +203,33 @@ impl SigSet {
97203
SigSet { sigset: sigset }
98204
}
99205

100-
pub fn add(&mut self, signum: SigNum) -> Result<()> {
101-
let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };
102-
103-
Errno::result(res).map(drop)
206+
pub fn add(&mut self, signal: Signal) {
207+
unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
104208
}
105209

106-
pub fn clear(&mut self) -> Result<()> {
107-
let res = unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
108-
109-
Errno::result(res).map(drop)
210+
pub fn clear(&mut self) {
211+
unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
110212
}
111213

112-
pub fn remove(&mut self, signum: SigNum) -> Result<()> {
113-
let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };
114-
115-
Errno::result(res).map(drop)
214+
pub fn remove(&mut self, signal: Signal) {
215+
unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
116216
}
117217

118-
pub fn extend(&mut self, other: &SigSet) -> Result<()> {
119-
for i in 1..NSIG {
120-
if try!(other.contains(i)) {
121-
try!(self.add(i));
122-
}
218+
pub fn contains(&self, signal: Signal) -> bool {
219+
let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
220+
221+
match res {
222+
1 => true,
223+
0 => false,
224+
_ => unreachable!("unexpected value from sigismember"),
123225
}
124-
Ok(())
125226
}
126227

127-
pub fn contains(&self, signum: SigNum) -> Result<bool> {
128-
let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };
129-
130-
match try!(Errno::result(res)) {
131-
1 => Ok(true),
132-
0 => Ok(false),
133-
_ => unreachable!("unexpected value from sigismember"),
228+
pub fn extend(&mut self, other: &SigSet) {
229+
for signal in Signal::iterator() {
230+
if other.contains(signal) {
231+
self.add(signal);
232+
}
134233
}
135234
}
136235

@@ -165,11 +264,11 @@ impl SigSet {
165264

166265
/// Suspends execution of the calling thread until one of the signals in the
167266
/// signal mask becomes pending, and returns the accepted signal.
168-
pub fn wait(&self) -> Result<SigNum> {
169-
let mut signum: SigNum = unsafe { mem::uninitialized() };
267+
pub fn wait(&self) -> Result<Signal> {
268+
let mut signum: libc::c_int = unsafe { mem::uninitialized() };
170269
let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
171270

172-
Errno::result(res).map(|_| signum)
271+
Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
173272
}
174273
}
175274

@@ -185,8 +284,8 @@ impl AsRef<libc::sigset_t> for SigSet {
185284
pub enum SigHandler {
186285
SigDfl,
187286
SigIgn,
188-
Handler(extern fn(SigNum)),
189-
SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
287+
Handler(extern fn(libc::c_int)),
288+
SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
190289
}
191290

192291
pub struct SigAction {
@@ -214,11 +313,11 @@ impl SigAction {
214313
}
215314
}
216315

217-
pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
316+
pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
218317
let mut oldact = mem::uninitialized::<libc::sigaction>();
219318

220319
let res =
221-
libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
320+
libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
222321

223322
Errno::result(res).map(|_| SigAction { sigaction: oldact })
224323
}
@@ -257,14 +356,14 @@ pub fn pthread_sigmask(how: SigFlags,
257356
Errno::result(res).map(drop)
258357
}
259358

260-
pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
261-
let res = unsafe { libc::kill(pid, signum) };
359+
pub fn kill(pid: libc::pid_t, signal: Signal) -> Result<()> {
360+
let res = unsafe { libc::kill(pid, signal as libc::c_int) };
262361

263362
Errno::result(res).map(drop)
264363
}
265364

266-
pub fn raise(signum: SigNum) -> Result<()> {
267-
let res = unsafe { libc::raise(signum) };
365+
pub fn raise(signal: Signal) -> Result<()> {
366+
let res = unsafe { libc::raise(signal as libc::c_int) };
268367

269368
Errno::result(res).map(drop)
270369
}
@@ -276,70 +375,70 @@ mod tests {
276375
#[test]
277376
fn test_contains() {
278377
let mut mask = SigSet::empty();
279-
mask.add(SIGUSR1).unwrap();
378+
mask.add(SIGUSR1);
280379

281-
assert_eq!(mask.contains(SIGUSR1), Ok(true));
282-
assert_eq!(mask.contains(SIGUSR2), Ok(false));
380+
assert!(mask.contains(SIGUSR1));
381+
assert!(!mask.contains(SIGUSR2));
283382

284383
let all = SigSet::all();
285-
assert_eq!(all.contains(SIGUSR1), Ok(true));
286-
assert_eq!(all.contains(SIGUSR2), Ok(true));
384+
assert!(all.contains(SIGUSR1));
385+
assert!(all.contains(SIGUSR2));
287386
}
288387

289388
#[test]
290389
fn test_clear() {
291390
let mut set = SigSet::all();
292-
set.clear().unwrap();
293-
for i in 1..NSIG {
294-
assert_eq!(set.contains(i), Ok(false));
391+
set.clear();
392+
for signal in Signal::iterator() {
393+
assert!(!set.contains(signal));
295394
}
296395
}
297396

298397
#[test]
299398
fn test_extend() {
300399
let mut one_signal = SigSet::empty();
301-
one_signal.add(SIGUSR1).unwrap();
400+
one_signal.add(SIGUSR1);
302401

303402
let mut two_signals = SigSet::empty();
304-
two_signals.add(SIGUSR2).unwrap();
305-
two_signals.extend(&one_signal).unwrap();
403+
two_signals.add(SIGUSR2);
404+
two_signals.extend(&one_signal);
306405

307-
assert_eq!(two_signals.contains(SIGUSR1), Ok(true));
308-
assert_eq!(two_signals.contains(SIGUSR2), Ok(true));
406+
assert!(two_signals.contains(SIGUSR1));
407+
assert!(two_signals.contains(SIGUSR2));
309408
}
310409

311410
#[test]
312411
fn test_thread_signal_block() {
313412
let mut mask = SigSet::empty();
314-
mask.add(SIGUSR1).unwrap();
413+
mask.add(SIGUSR1);
315414

316415
assert!(mask.thread_block().is_ok());
317416
}
318417

319418
#[test]
320419
fn test_thread_signal_swap() {
321420
let mut mask = SigSet::empty();
322-
mask.add(SIGUSR1).unwrap();
421+
mask.add(SIGUSR1);
323422
mask.thread_block().unwrap();
324423

325-
assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());
424+
assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
326425

327426
let mask2 = SigSet::empty();
328-
mask.add(SIGUSR2).unwrap();
427+
mask.add(SIGUSR2);
329428

330429
let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();
331430

332-
assert!(oldmask.contains(SIGUSR1).unwrap());
333-
assert!(!oldmask.contains(SIGUSR2).unwrap());
431+
assert!(oldmask.contains(SIGUSR1));
432+
assert!(!oldmask.contains(SIGUSR2));
334433
}
335434

336435
// TODO(#251): Re-enable after figuring out flakiness.
337436
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
338437
#[test]
339438
fn test_sigwait() {
340439
let mut mask = SigSet::empty();
341-
mask.add(SIGUSR1).unwrap();
342-
mask.add(SIGUSR2).unwrap();
440+
mask.add(SIGUSR1);
441+
mask.add(SIGUSR2);
343442
mask.thread_block().unwrap();
344443

345444
raise(SIGUSR1).unwrap();

0 commit comments

Comments
 (0)