4
4
use libc;
5
5
use errno:: Errno ;
6
6
use std:: mem;
7
+ use std:: ptr;
7
8
use { Error , Result } ;
8
9
9
10
pub use libc:: consts:: os:: posix88:: {
@@ -43,6 +44,7 @@ pub use self::signal::{
43
44
} ;
44
45
45
46
pub use self :: signal:: SockFlag ;
47
+ pub use self :: signal:: { HowFlag , SIG_BLOCK , SIG_UNBLOCK , SIG_SETMASK } ;
46
48
pub use self :: signal:: sigset_t;
47
49
48
50
// This doesn't always exist, but when it does, it's 7
@@ -68,6 +70,14 @@ pub mod signal {
68
70
}
69
71
) ;
70
72
73
+ bitflags ! {
74
+ flags HowFlag : libc:: c_int {
75
+ const SIG_BLOCK = 0 ,
76
+ const SIG_UNBLOCK = 1 ,
77
+ const SIG_SETMASK = 2 ,
78
+ }
79
+ }
80
+
71
81
pub const SIGTRAP : libc:: c_int = 5 ;
72
82
pub const SIGIOT : libc:: c_int = 6 ;
73
83
pub const SIGBUS : libc:: c_int = 7 ;
@@ -98,9 +108,9 @@ pub mod signal {
98
108
#[ repr( C ) ]
99
109
#[ derive( Clone , Copy ) ]
100
110
pub struct siginfo {
101
- si_signo : libc:: c_int ,
102
- si_errno : libc:: c_int ,
103
- si_code : libc:: c_int ,
111
+ pub si_signo : libc:: c_int ,
112
+ pub si_errno : libc:: c_int ,
113
+ pub si_code : libc:: c_int ,
104
114
pub pid : libc:: pid_t ,
105
115
pub uid : libc:: uid_t ,
106
116
pub status : libc:: c_int ,
@@ -147,6 +157,14 @@ pub mod signal {
147
157
}
148
158
) ;
149
159
160
+ bitflags ! {
161
+ flags HowFlag : libc:: c_int {
162
+ const SIG_BLOCK = 1 ,
163
+ const SIG_UNBLOCK = 2 ,
164
+ const SIG_SETMASK = 3 ,
165
+ }
166
+ }
167
+
150
168
pub const SIGTRAP : libc:: c_int = 5 ;
151
169
pub const SIGIOT : libc:: c_int = 6 ;
152
170
pub const SIGBUS : libc:: c_int = 10 ;
@@ -175,9 +193,9 @@ pub mod signal {
175
193
// however.
176
194
#[ repr( C ) ]
177
195
pub struct siginfo {
178
- si_signo : libc:: c_int ,
179
- si_code : libc:: c_int ,
180
- si_errno : libc:: c_int ,
196
+ pub si_signo : libc:: c_int ,
197
+ pub si_code : libc:: c_int ,
198
+ pub si_errno : libc:: c_int ,
181
199
pub pid : libc:: pid_t ,
182
200
pub uid : libc:: uid_t ,
183
201
pub status : libc:: c_int ,
@@ -218,6 +236,14 @@ pub mod signal {
218
236
}
219
237
) ;
220
238
239
+ bitflags ! {
240
+ flags HowFlag : libc:: c_int {
241
+ const SIG_BLOCK = 1 ,
242
+ const SIG_UNBLOCK = 2 ,
243
+ const SIG_SETMASK = 3 ,
244
+ }
245
+ }
246
+
221
247
pub const SIGTRAP : libc:: c_int = 5 ;
222
248
pub const SIGIOT : libc:: c_int = 6 ;
223
249
pub const SIGBUS : libc:: c_int = 10 ;
@@ -307,20 +333,24 @@ pub mod signal {
307
333
}
308
334
309
335
mod ffi {
310
- use libc;
336
+ use libc:: { c_int , pid_t } ;
311
337
use super :: signal:: { sigaction, sigset_t} ;
312
338
313
339
#[ allow( improper_ctypes) ]
314
340
extern {
315
- pub fn sigaction ( signum : libc :: c_int ,
341
+ pub fn sigaction ( signum : c_int ,
316
342
act : * const sigaction ,
317
- oldact : * mut sigaction ) -> libc :: c_int ;
343
+ oldact : * mut sigaction ) -> c_int ;
318
344
319
- pub fn sigaddset ( set : * mut sigset_t , signum : libc:: c_int ) -> libc:: c_int ;
320
- pub fn sigdelset ( set : * mut sigset_t , signum : libc:: c_int ) -> libc:: c_int ;
321
- pub fn sigemptyset ( set : * mut sigset_t ) -> libc:: c_int ;
345
+ pub fn sigaddset ( set : * mut sigset_t , signum : c_int ) -> c_int ;
346
+ pub fn sigdelset ( set : * mut sigset_t , signum : c_int ) -> c_int ;
347
+ pub fn sigemptyset ( set : * mut sigset_t ) -> c_int ;
348
+ pub fn sigfillset ( set : * mut sigset_t ) -> c_int ;
349
+ pub fn sigismember ( set : * const sigset_t , signum : c_int ) -> c_int ;
322
350
323
- pub fn kill ( pid : libc:: pid_t , signum : libc:: c_int ) -> libc:: c_int ;
351
+ pub fn pthread_sigmask ( how : c_int , set : * const sigset_t , oldset : * mut sigset_t ) -> c_int ;
352
+
353
+ pub fn kill ( pid : pid_t , signum : c_int ) -> c_int ;
324
354
}
325
355
}
326
356
@@ -332,8 +362,15 @@ pub struct SigSet {
332
362
pub type SigNum = libc:: c_int ;
333
363
334
364
impl SigSet {
365
+ pub fn all ( ) -> SigSet {
366
+ let mut sigset: sigset_t = unsafe { mem:: uninitialized ( ) } ;
367
+ let _ = unsafe { ffi:: sigfillset ( & mut sigset as * mut sigset_t ) } ;
368
+
369
+ SigSet { sigset : sigset }
370
+ }
371
+
335
372
pub fn empty ( ) -> SigSet {
336
- let mut sigset = unsafe { mem:: uninitialized :: < sigset_t > ( ) } ;
373
+ let mut sigset: sigset_t = unsafe { mem:: uninitialized ( ) } ;
337
374
let _ = unsafe { ffi:: sigemptyset ( & mut sigset as * mut sigset_t ) } ;
338
375
339
376
SigSet { sigset : sigset }
@@ -358,6 +395,51 @@ impl SigSet {
358
395
359
396
Ok ( ( ) )
360
397
}
398
+
399
+ pub fn contains ( & self , signum : SigNum ) -> Result < bool > {
400
+ let res = unsafe { ffi:: sigismember ( & self . sigset as * const sigset_t , signum) } ;
401
+
402
+ match res {
403
+ 1 => Ok ( true ) ,
404
+ 0 => Ok ( false ) ,
405
+ _ => Err ( Error :: Sys ( Errno :: last ( ) ) )
406
+ }
407
+ }
408
+
409
+ /// Gets the currently blocked (masked) set of signals for the calling thread.
410
+ pub fn thread_get_mask ( ) -> Result < SigSet > {
411
+ let mut oldmask: SigSet = unsafe { mem:: uninitialized ( ) } ;
412
+ try!( pthread_sigmask ( HowFlag :: empty ( ) , None , Some ( & mut oldmask) ) ) ;
413
+ Ok ( oldmask)
414
+ }
415
+
416
+ /// Sets the set of signals as the signal mask for the calling thread.
417
+ pub fn thread_set_mask ( & self ) -> Result < ( ) > {
418
+ pthread_sigmask ( SIG_SETMASK , Some ( self ) , None )
419
+ }
420
+
421
+ /// Adds the set of signals to the signal mask for the calling thread.
422
+ pub fn thread_block ( & self ) -> Result < ( ) > {
423
+ pthread_sigmask ( SIG_BLOCK , Some ( self ) , None )
424
+ }
425
+
426
+ /// Removes the set of signals from the signal mask for the calling thread.
427
+ pub fn thread_unblock ( & self ) -> Result < ( ) > {
428
+ pthread_sigmask ( SIG_UNBLOCK , Some ( self ) , None )
429
+ }
430
+
431
+ /// Sets the set of signals as the signal mask, and returns the old mask.
432
+ pub fn thread_swap_mask ( & self , how : HowFlag ) -> Result < SigSet > {
433
+ let mut oldmask: SigSet = unsafe { mem:: uninitialized ( ) } ;
434
+ try!( pthread_sigmask ( how, Some ( self ) , Some ( & mut oldmask) ) ) ;
435
+ Ok ( oldmask)
436
+ }
437
+ }
438
+
439
+ impl AsRef < sigset_t > for SigSet {
440
+ fn as_ref ( & self ) -> & sigset_t {
441
+ & self . sigset
442
+ }
361
443
}
362
444
363
445
type sigaction_t = self :: signal:: sigaction ;
@@ -390,6 +472,44 @@ pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigActi
390
472
Ok ( SigAction { sigaction : oldact } )
391
473
}
392
474
475
+ /// Manages the signal mask (set of blocked signals) for the calling thread.
476
+ ///
477
+ /// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
478
+ /// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
479
+ /// and no modification will take place.
480
+ ///
481
+ /// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
482
+ ///
483
+ /// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
484
+ /// and then it will be updated with `set`.
485
+ ///
486
+ /// If both `set` and `oldset` is None, this function is a no-op.
487
+ ///
488
+ /// For more information, visit the [pthread_sigmask](http://man7.org/linux/man-pages/man3/pthread_sigmask.3.html),
489
+ /// or [sigprocmask](http://man7.org/linux/man-pages/man2/sigprocmask.2.html) man pages.
490
+ pub fn pthread_sigmask ( how : HowFlag ,
491
+ set : Option < & SigSet > ,
492
+ oldset : Option < & mut SigSet > ) -> Result < ( ) > {
493
+ if set. is_none ( ) && oldset. is_none ( ) {
494
+ return Ok ( ( ) )
495
+ }
496
+
497
+ let res = unsafe {
498
+ // if set or oldset is None, pass in null pointers instead
499
+ ffi:: pthread_sigmask ( how. bits ( ) ,
500
+ set. map_or_else ( || ptr:: null :: < sigset_t > ( ) ,
501
+ |s| & s. sigset as * const sigset_t ) ,
502
+ oldset. map_or_else ( || ptr:: null_mut :: < sigset_t > ( ) ,
503
+ |os| & mut os. sigset as * mut sigset_t ) )
504
+ } ;
505
+
506
+ if res != 0 {
507
+ return Err ( Error :: Sys ( Errno :: last ( ) ) ) ;
508
+ }
509
+
510
+ Ok ( ( ) )
511
+ }
512
+
393
513
pub fn kill ( pid : libc:: pid_t , signum : SigNum ) -> Result < ( ) > {
394
514
let res = unsafe { ffi:: kill ( pid, signum) } ;
395
515
@@ -399,3 +519,46 @@ pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
399
519
400
520
Ok ( ( ) )
401
521
}
522
+
523
+ #[ cfg( test) ]
524
+ mod tests {
525
+ use super :: * ;
526
+
527
+ #[ test]
528
+ fn test_contains ( ) {
529
+ let mut mask = SigSet :: empty ( ) ;
530
+ mask. add ( signal:: SIGUSR1 ) . unwrap ( ) ;
531
+
532
+ assert_eq ! ( mask. contains( signal:: SIGUSR1 ) , Ok ( true ) ) ;
533
+ assert_eq ! ( mask. contains( signal:: SIGUSR2 ) , Ok ( false ) ) ;
534
+
535
+ let all = SigSet :: all ( ) ;
536
+ assert_eq ! ( all. contains( signal:: SIGUSR1 ) , Ok ( true ) ) ;
537
+ assert_eq ! ( all. contains( signal:: SIGUSR2 ) , Ok ( true ) ) ;
538
+ }
539
+
540
+ #[ test]
541
+ fn test_thread_signal_block ( ) {
542
+ let mut mask = SigSet :: empty ( ) ;
543
+ mask. add ( signal:: SIGUSR1 ) . unwrap ( ) ;
544
+
545
+ assert ! ( mask. thread_block( ) . is_ok( ) ) ;
546
+ }
547
+
548
+ #[ test]
549
+ fn test_thread_signal_swap ( ) {
550
+ let mut mask = SigSet :: empty ( ) ;
551
+ mask. add ( signal:: SIGUSR1 ) . unwrap ( ) ;
552
+ mask. thread_block ( ) . unwrap ( ) ;
553
+
554
+ assert ! ( SigSet :: thread_get_mask( ) . unwrap( ) . contains( SIGUSR1 ) . unwrap( ) ) ;
555
+
556
+ let mask2 = SigSet :: empty ( ) ;
557
+ mask. add ( signal:: SIGUSR2 ) . unwrap ( ) ;
558
+
559
+ let oldmask = mask2. thread_swap_mask ( signal:: SIG_SETMASK ) . unwrap ( ) ;
560
+
561
+ assert ! ( oldmask. contains( signal:: SIGUSR1 ) . unwrap( ) ) ;
562
+ assert ! ( !oldmask. contains( signal:: SIGUSR2 ) . unwrap( ) ) ;
563
+ }
564
+ }
0 commit comments