1
1
//! A simple wrapper for handling Unix process signals.
2
2
3
- #![ cfg_attr( feature="nightly" , feature( static_condvar) ) ]
4
- #![ cfg_attr( feature="nightly" , feature( static_mutex) ) ]
5
-
6
- #[ cfg( feature="stable" ) ]
7
- #[ macro_use]
8
- extern crate lazy_static;
9
-
10
3
use std:: sync:: atomic:: Ordering ;
11
- use std:: thread;
12
4
13
5
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
14
6
pub enum Signal {
@@ -25,35 +17,20 @@ pub enum Signal {
25
17
Term ,
26
18
}
27
19
28
- #[ cfg( feature="nightly" ) ]
29
- mod features {
30
- use std:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT } ;
31
- use std:: sync:: { StaticCondvar , CONDVAR_INIT , StaticMutex , MUTEX_INIT } ;
32
- pub static CVAR : StaticCondvar = CONDVAR_INIT ;
33
- pub static MUTEX : StaticMutex = MUTEX_INIT ;
34
- pub static MASK : AtomicUsize = ATOMIC_USIZE_INIT ;
20
+ use std:: sync:: atomic:: AtomicUsize ;
21
+ use std:: sync:: { Condvar , Mutex } ;
22
+ lazy_static:: lazy_static! {
23
+ pub static ref CVAR : Condvar = Condvar :: new( ) ;
24
+ pub static ref MUTEX : Mutex <( ) > = Mutex :: new( ( ) ) ;
35
25
}
36
-
37
- #[ cfg( not( feature="nightly" ) ) ]
38
- mod features {
39
- use std:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT } ;
40
- use std:: sync:: { Condvar , Mutex } ;
41
- lazy_static ! {
42
- pub static ref CVAR : Condvar = Condvar :: new( ) ;
43
- pub static ref MUTEX : Mutex <bool > = Mutex :: new( false ) ;
44
- }
45
- pub static MASK : AtomicUsize = ATOMIC_USIZE_INIT ;
46
- }
47
-
48
- use self :: features:: * ;
26
+ pub static MASK : AtomicUsize = AtomicUsize :: new ( 0 ) ;
49
27
50
28
#[ cfg( unix) ]
51
29
mod platform {
52
30
extern crate libc;
53
31
54
32
use self :: libc:: { c_int, signal, sighandler_t} ;
55
33
use self :: libc:: { SIGHUP , SIGINT , SIGQUIT , SIGILL , SIGABRT , SIGFPE , SIGKILL , SIGSEGV , SIGPIPE , SIGALRM , SIGTERM } ;
56
- use std:: mem;
57
34
use std:: sync:: atomic:: Ordering ;
58
35
use super :: Signal ;
59
36
@@ -74,13 +51,13 @@ mod platform {
74
51
} ;
75
52
76
53
loop {
77
- let prev_mask = super :: features :: MASK . load ( Ordering :: Relaxed ) ;
54
+ let prev_mask = super :: MASK . load ( Ordering :: Relaxed ) ;
78
55
let new_mask = prev_mask | mask;
79
- if super :: features :: MASK . compare_and_swap ( prev_mask, new_mask, Ordering :: Relaxed ) == new_mask {
56
+ if super :: MASK . compare_exchange ( prev_mask, new_mask, Ordering :: Relaxed , Ordering :: Relaxed ) . is_ok ( ) {
80
57
break ;
81
58
}
82
59
}
83
- super :: features :: CVAR . notify_all ( ) ;
60
+ super :: CVAR . notify_all ( ) ;
84
61
}
85
62
86
63
#[ inline]
@@ -99,7 +76,7 @@ mod platform {
99
76
Signal :: Term => SIGTERM ,
100
77
} ;
101
78
102
- signal ( os_sig, mem :: transmute :: < _ , sighandler_t > ( handler as extern "C" fn ( _) ) ) ;
79
+ signal ( os_sig, handler as extern "C" fn ( _) as sighandler_t ) ;
103
80
}
104
81
}
105
82
@@ -112,17 +89,17 @@ use self::platform::*;
112
89
/// use simple_signal::{self, Signal};
113
90
/// simple_signal::set_handler(&[Signal::Int, Signal::Term], |signals| println!("Caught: {:?}", signals));
114
91
/// ```
115
- pub fn set_handler < F > ( signals : & [ Signal ] , user_handler : F ) where F : Fn ( & [ Signal ] ) + ' static + Send {
92
+ pub fn set_handler < F > ( signals : & [ Signal ] , mut user_handler : F ) where F : FnMut ( & [ Signal ] ) + ' static + Send {
116
93
for & signal in signals. iter ( ) {
117
94
unsafe { set_os_handler ( signal) }
118
95
}
119
- thread:: spawn ( move || {
96
+ std :: thread:: spawn ( move || {
120
97
let mut signals = Vec :: new ( ) ;
98
+ let mut guard = MUTEX . lock ( ) . unwrap ( ) ;
121
99
loop {
122
- let mask = MASK . load ( Ordering :: Relaxed ) ;
100
+ let mask = MASK . swap ( 0 , Ordering :: Relaxed ) ;
123
101
if mask == 0 {
124
- let _ = CVAR . wait ( MUTEX . lock ( ) . unwrap ( ) ) ;
125
- thread:: yield_now ( ) ;
102
+ guard = CVAR . wait ( guard) . unwrap ( ) ;
126
103
continue ;
127
104
}
128
105
signals. clear ( ) ;
@@ -137,7 +114,6 @@ pub fn set_handler<F>(signals: &[Signal], user_handler: F) where F: Fn(&[Signal]
137
114
if mask & 256 != 0 { signals. push ( Signal :: Pipe ) }
138
115
if mask & 512 != 0 { signals. push ( Signal :: Alrm ) }
139
116
if mask & 1024 != 0 { signals. push ( Signal :: Term ) }
140
- MASK . store ( 0 , Ordering :: Relaxed ) ;
141
117
user_handler ( & signals) ;
142
118
}
143
119
} ) ;
@@ -150,7 +126,7 @@ mod test {
150
126
use std:: sync:: mpsc:: sync_channel;
151
127
use self :: libc:: c_int;
152
128
use self :: libc:: { SIGHUP , SIGINT , SIGQUIT , SIGILL , SIGABRT , SIGFPE , SIGKILL , SIGSEGV , SIGPIPE , SIGALRM , SIGTERM } ;
153
- use super :: { Signal } ;
129
+ use super :: Signal ;
154
130
use super :: platform:: handler;
155
131
156
132
fn to_os_signal ( signal : Signal ) -> c_int {
@@ -173,7 +149,12 @@ mod test {
173
149
fn all_signals ( ) {
174
150
let signals = [ Signal :: Hup , Signal :: Int , Signal :: Quit , Signal :: Abrt , Signal :: Term ] ;
175
151
let ( tx, rx) = sync_channel ( 0 ) ;
176
- super :: set_handler ( & signals, move |signals| tx. send ( signals. to_owned ( ) ) . unwrap ( ) ) ;
152
+ let mut signal_count = 0 ;
153
+ super :: set_handler ( & signals, move |signals| {
154
+ signal_count += signals. len ( ) ;
155
+ println ! ( "Handled {} signals" , signal_count) ;
156
+ tx. send ( signals. to_owned ( ) ) . unwrap ( ) ;
157
+ } ) ;
177
158
// Check all signals one-by-one.
178
159
for & signal in signals. iter ( ) {
179
160
handler ( to_os_signal ( signal) ) ;
0 commit comments