File Coverage

blib/lib/Signal/Mask.pm
Criterion Covered Total %
statement 41 60 68.3
branch 3 8 37.5
condition n/a
subroutine 13 19 68.4
pod n/a
total 57 87 65.5


line stmt bran cond sub pod time code
1             package Signal::Mask;
2             $Signal::Mask::VERSION = '0.008';
3 1     1   23206 use strict;
  1         2  
  1         41  
4 1     1   5 use warnings FATAL => 'all';
  1         3  
  1         36  
5              
6 1     1   5 use Config;
  1         2  
  1         52  
7 1     1   872 use POSIX qw/SIG_BLOCK SIG_UNBLOCK SIG_SETMASK/;
  1         7474  
  1         7  
8             BEGIN {
9 1 50   1   6421 if (eval { require Thread::SigMask }) {
  1         1051  
10 1         785 *sigmask = \&Thread::SigMask::sigmask;
11             }
12             else {
13 0         0 require POSIX;
14 0         0 *sigmask = \&POSIX::sigprocmask;
15             }
16             }
17 1     1   1026 use IPC::Signal qw/sig_num sig_name/;
  1         644  
  1         75  
18 1     1   7 use Carp qw/croak/;
  1         2  
  1         940  
19              
20             my $sig_max = $Config{sig_count} - 1;
21              
22             tie %Signal::Mask, __PACKAGE__;
23              
24             sub TIEHASH {
25 1     1   4 my $class = shift;
26 1         4 my $self = { iterator => 1, };
27 1         6 return bless $self, $class;
28             }
29              
30             sub _get_status {
31 1     1   6 my ($self, $num) = @_;
32 1         5 my $mask = POSIX::SigSet->new;
33 1         9 sigmask(SIG_BLOCK, POSIX::SigSet->new(), $mask);
34 1         9 return $mask->ismember($num);
35             }
36              
37             sub FETCH {
38 1     1   398 my ($self, $key) = @_;
39 1         13 return $self->_get_status(sig_num($key));
40             }
41              
42             my $block_signal = sub {
43             my ($self, $key) = @_;
44             my $num = sig_num($key);
45             croak "No such signal '$key'" if not defined $num;
46             sigmask(SIG_BLOCK, POSIX::SigSet->new($num)) or croak "Couldn't block signal: $!";
47             return;
48             };
49              
50             my $unblock_signal = sub {
51             my ($self, $key) = @_;
52             my $num = sig_num($key);
53             croak "No such signal '$key'" if not defined $num;
54             my $ret = POSIX::SigSet->new($num);
55             sigmask(SIG_UNBLOCK, POSIX::SigSet->new($num), $ret) or croak "Couldn't unblock signal: $!";
56             return $ret->ismember($num);
57             };
58              
59             sub STORE {
60 2     2   446 my ($self, $key, $value) = @_;
61 2 100       7 my $method = $value ? $block_signal : $unblock_signal;
62 2         7 $self->$method($key);
63 2         6 return;
64             }
65              
66             sub DELETE {
67 0     0   0 my ($self, $key) = @_;
68 0         0 return $self->$unblock_signal($key);
69             }
70              
71             sub CLEAR {
72 0     0   0 my ($self) = @_;
73 0         0 sigmask(SIG_SETMASK, POSIX::SigSet->new());
74 0         0 return;
75             }
76              
77             sub EXISTS {
78 1     1   2 my ($self, $key) = @_;
79 1         10 return defined sig_num($key);
80             }
81              
82             sub FIRSTKEY {
83 0     0   0 my $self = shift;
84 0         0 $self->{iterator} = 1;
85 0         0 return $self->NEXTKEY;
86             }
87              
88             sub NEXTKEY {
89 0     0   0 my $self = shift;
90 0 0       0 if ($self->{iterator} <= $sig_max) {
91 0         0 my $num = $self->{iterator}++;
92 0 0       0 return wantarray ? (sig_name($num) => $self->_get_status($num)) : sig_name($num);
93             }
94             else {
95 0         0 return;
96             }
97             }
98              
99             sub SCALAR {
100 2     2   17 my $self = shift;
101 2         27 my $mask = POSIX::SigSet->new;
102 2         21 sigmask(SIG_BLOCK, POSIX::SigSet->new(), $mask);
103 2         40 return scalar grep { $mask->ismember($_) } 1 .. $sig_max;
  128         238  
104             }
105              
106             sub UNTIE {
107 0     0     my $self = shift;
108 0           $self->CLEAR;
109 0           return;
110             }
111              
112 0     0     sub DESTROY {
113             }
114              
115             1; # End of Signal::Mask
116              
117             # ABSTRACT: Signal masks made easy
118              
119             __END__