1
- //! A simple easy to use wrapper around unix signals.
1
+ //! A simple wrapper for handling Unix process signals.
2
2
3
3
#![ cfg_attr( feature="nightly" , feature( static_condvar) ) ]
4
4
#![ cfg_attr( feature="nightly" , feature( static_mutex) ) ]
8
8
extern crate lazy_static;
9
9
10
10
use std:: sync:: atomic:: Ordering ;
11
+ use std:: thread;
11
12
12
13
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
13
14
pub enum Signal {
@@ -32,6 +33,7 @@ mod features {
32
33
pub static MUTEX : StaticMutex = MUTEX_INIT ;
33
34
pub static MASK : AtomicUsize = ATOMIC_USIZE_INIT ;
34
35
}
36
+
35
37
#[ cfg( not( feature="nightly" ) ) ]
36
38
mod features {
37
39
use std:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT } ;
@@ -42,13 +44,16 @@ mod features {
42
44
}
43
45
pub static MASK : AtomicUsize = ATOMIC_USIZE_INIT ;
44
46
}
47
+
45
48
use self :: features:: * ;
46
49
47
50
#[ cfg( unix) ]
48
51
mod platform {
49
52
extern crate libc;
53
+
50
54
use self :: libc:: { c_int, signal, sighandler_t} ;
51
55
use self :: libc:: { SIGHUP , SIGINT , SIGQUIT , SIGILL , SIGABRT , SIGFPE , SIGKILL , SIGSEGV , SIGPIPE , SIGALRM , SIGTERM } ;
56
+ use std:: mem;
52
57
use std:: sync:: atomic:: Ordering ;
53
58
use super :: Signal ;
54
59
@@ -72,11 +77,12 @@ mod platform {
72
77
let prev_mask = super :: features:: MASK . load ( Ordering :: Relaxed ) ;
73
78
let new_mask = prev_mask | mask;
74
79
if super :: features:: MASK . compare_and_swap ( prev_mask, new_mask, Ordering :: Relaxed ) == new_mask {
75
- break
80
+ break ;
76
81
}
77
82
}
78
83
super :: features:: CVAR . notify_all ( ) ;
79
84
}
85
+
80
86
#[ inline]
81
87
pub unsafe fn set_os_handler ( sig : Signal ) {
82
88
let os_sig = match sig {
@@ -93,58 +99,58 @@ mod platform {
93
99
Signal :: Term => SIGTERM ,
94
100
} ;
95
101
96
- signal ( os_sig, :: std :: mem:: transmute :: < _ , sighandler_t > ( handler as extern "C" fn ( _) ) ) ;
102
+ signal ( os_sig, mem:: transmute :: < _ , sighandler_t > ( handler as extern "C" fn ( _) ) ) ;
97
103
}
98
104
}
99
105
100
106
use self :: platform:: * ;
101
107
102
- pub struct Signals ;
103
- impl Signals {
104
- /// Sets up some signals handler
105
- /// # Example
106
- /// ```
107
- /// use simple_signal::{Signals, Signal};
108
- /// Signals::set_handler(&[Signal::Int, Signal::Term], |signals| println!("Caught: {:?}", signals));
109
- /// ```
110
- pub fn set_handler < F > ( signals : & [ Signal ] , user_handler : F ) where F : Fn ( & [ Signal ] ) + ' static + Send {
111
- for & signal in signals. iter ( ) {
112
- unsafe { set_os_handler ( signal) }
113
- }
114
- :: std:: thread:: spawn ( move || {
115
- let mut signals = Vec :: new ( ) ;
116
- loop {
117
- let mask = MASK . load ( Ordering :: Relaxed ) ;
118
- if mask == 0 {
119
- let _ = CVAR . wait ( MUTEX . lock ( ) . unwrap ( ) ) ;
120
- continue
121
- }
122
- signals. clear ( ) ;
123
- if mask & 1 != 0 { signals. push ( Signal :: Hup ) }
124
- if mask & 2 != 0 { signals. push ( Signal :: Int ) }
125
- if mask & 4 != 0 { signals. push ( Signal :: Quit ) }
126
- if mask & 8 != 0 { signals. push ( Signal :: Ill ) }
127
- if mask & 16 != 0 { signals. push ( Signal :: Abrt ) }
128
- if mask & 32 != 0 { signals. push ( Signal :: Fpe ) }
129
- if mask & 64 != 0 { signals. push ( Signal :: Kill ) }
130
- if mask & 128 != 0 { signals. push ( Signal :: Segv ) }
131
- if mask & 256 != 0 { signals. push ( Signal :: Pipe ) }
132
- if mask & 512 != 0 { signals. push ( Signal :: Alrm ) }
133
- if mask & 1024 != 0 { signals. push ( Signal :: Term ) }
134
- MASK . store ( 0 , Ordering :: Relaxed ) ;
135
- user_handler ( & signals) ;
136
- }
137
- } ) ;
108
+ /// Sets up a signal handler.
109
+ ///
110
+ /// # Example
111
+ /// ```
112
+ /// use simple_signal::{self, Signal};
113
+ /// simple_signal::set_handler(&[Signal::Int, Signal::Term], |signals| println!("Caught: {:?}", signals));
114
+ /// ```
115
+ pub fn set_handler < F > ( signals : & [ Signal ] , user_handler : F ) where F : Fn ( & [ Signal ] ) + ' static + Send {
116
+ for & signal in signals. iter ( ) {
117
+ unsafe { set_os_handler ( signal) }
138
118
}
119
+ thread:: spawn ( move || {
120
+ let mut signals = Vec :: new ( ) ;
121
+ loop {
122
+ let mask = MASK . load ( Ordering :: Relaxed ) ;
123
+ if mask == 0 {
124
+ let _ = CVAR . wait ( MUTEX . lock ( ) . unwrap ( ) ) ;
125
+ thread:: yield_now ( ) ;
126
+ continue ;
127
+ }
128
+ signals. clear ( ) ;
129
+ if mask & 1 != 0 { signals. push ( Signal :: Hup ) }
130
+ if mask & 2 != 0 { signals. push ( Signal :: Int ) }
131
+ if mask & 4 != 0 { signals. push ( Signal :: Quit ) }
132
+ if mask & 8 != 0 { signals. push ( Signal :: Ill ) }
133
+ if mask & 16 != 0 { signals. push ( Signal :: Abrt ) }
134
+ if mask & 32 != 0 { signals. push ( Signal :: Fpe ) }
135
+ if mask & 64 != 0 { signals. push ( Signal :: Kill ) }
136
+ if mask & 128 != 0 { signals. push ( Signal :: Segv ) }
137
+ if mask & 256 != 0 { signals. push ( Signal :: Pipe ) }
138
+ if mask & 512 != 0 { signals. push ( Signal :: Alrm ) }
139
+ if mask & 1024 != 0 { signals. push ( Signal :: Term ) }
140
+ MASK . store ( 0 , Ordering :: Relaxed ) ;
141
+ user_handler ( & signals) ;
142
+ }
143
+ } ) ;
139
144
}
140
145
141
146
#[ cfg( test) ]
142
147
mod test {
143
148
extern crate libc;
149
+
144
150
use std:: sync:: mpsc:: sync_channel;
145
151
use self :: libc:: c_int;
146
152
use self :: libc:: { SIGHUP , SIGINT , SIGQUIT , SIGILL , SIGABRT , SIGFPE , SIGKILL , SIGSEGV , SIGPIPE , SIGALRM , SIGTERM } ;
147
- use super :: { Signal , Signals } ;
153
+ use super :: { Signal } ;
148
154
use super :: platform:: handler;
149
155
150
156
fn to_os_signal ( signal : Signal ) -> c_int {
@@ -167,13 +173,13 @@ mod test {
167
173
fn all_signals ( ) {
168
174
let signals = [ Signal :: Hup , Signal :: Int , Signal :: Quit , Signal :: Abrt , Signal :: Term ] ;
169
175
let ( tx, rx) = sync_channel ( 0 ) ;
170
- Signals :: set_handler ( & signals, move |signals| tx. send ( signals. to_owned ( ) ) . unwrap ( ) ) ;
171
- // check one by one
176
+ super :: set_handler ( & signals, move |signals| tx. send ( signals. to_owned ( ) ) . unwrap ( ) ) ;
177
+ // Check all signals one-by-one.
172
178
for & signal in signals. iter ( ) {
173
179
handler ( to_os_signal ( signal) ) ;
174
180
assert_eq ! ( rx. recv( ) . unwrap( ) , vec![ signal] ) ;
175
181
}
176
- // check all simultaneously
182
+ // Check all signals simultaneously.
177
183
for & signal in signals. iter ( ) {
178
184
handler ( to_os_signal ( signal) )
179
185
}
0 commit comments