File Coverage

blib/lib/POE/Loop/PerlSignals.pm
Criterion Covered Total %
statement 51 52 98.0
branch 10 10 100.0
condition 5 6 83.3
subroutine 13 13 100.0
pod 0 3 0.0
total 79 84 94.0


line stmt bran cond sub pod time code
1             # Plain Perl signal handling is something shared by several event
2             # loops. The invariant code has moved out here so that each loop may
3             # use it without reinventing it. This will save maintenance and
4             # shrink the distribution. Yay!
5              
6             package POE::Loop::PerlSignals;
7              
8 176     176   781 use strict;
  176         254  
  176         6516  
9              
10 176     176   804 use vars qw($VERSION);
  176         226  
  176         9497  
11             $VERSION = '1.366'; # NOTE - Should be #.### (three decimal places)
12              
13             # Everything plugs into POE::Kernel.
14             package POE::Kernel;
15              
16 176     176   781 use strict;
  176         250  
  176         3618  
17 176     176   2475 use POE::Kernel;
  176         252  
  176         1487  
18              
19             # Flag so we know which signals are watched. Used to reset those
20             # signals during finalization.
21             my %signal_watched;
22              
23             #------------------------------------------------------------------------------
24             # Signal handlers/callbacks.
25              
26             sub _loop_signal_handler_generic {
27 16     16   506 if( USE_SIGNAL_PIPE ) {
28 16         211 POE::Kernel->_data_sig_pipe_send( $_[0] );
29             }
30             else {
31             _loop_signal_handler_generic_bottom( $_[0] );
32             }
33             }
34              
35             sub _loop_signal_handler_generic_bottom {
36 16     16   23 if (TRACE_SIGNALS) {
37             POE::Kernel::_warn " Enqueuing generic SIG$_[0] event";
38             }
39              
40             $poe_kernel->_data_ev_enqueue(
41 16         123 $poe_kernel, $poe_kernel, EN_SIGNAL, ET_SIGNAL, [ $_[0] ],
42             __FILE__, __LINE__, undef
43             );
44 16         275 $SIG{$_[0]} = \&_loop_signal_handler_generic;
45             }
46              
47             ##
48              
49             sub _loop_signal_handler_pipe {
50 28     12   303 if( USE_SIGNAL_PIPE ) {
51 12         63 POE::Kernel->_data_sig_pipe_send( $_[0] );
52             }
53             else {
54             _loop_signal_handler_pipe_bottom( $_[0] );
55             }
56             }
57              
58             sub _loop_signal_handler_pipe_bottom {
59 12     12   17 if (TRACE_SIGNALS) {
60             POE::Kernel::_warn " Enqueuing PIPE-like SIG$_[0] event";
61             }
62              
63             $poe_kernel->_data_ev_enqueue(
64 12         51 $poe_kernel, $poe_kernel, EN_SIGNAL, ET_SIGNAL, [ $_[0] ],
65             __FILE__, __LINE__, undef
66             );
67 12         81 $SIG{$_[0]} = \&_loop_signal_handler_pipe;
68             }
69              
70             ## only used under USE_SIGCHLD
71              
72             sub _loop_signal_handler_chld {
73 215     203   18530 if( USE_SIGNAL_PIPE ) {
74 203         17610 POE::Kernel->_data_sig_pipe_send( 'CHLD' );
75             }
76             else {
77             _loop_signal_handler_chld_bottom( $_[0] );
78             }
79             }
80              
81             sub _loop_signal_handler_chld_bottom {
82 203     203   244 if (TRACE_SIGNALS) {
83             POE::Kernel::_warn " Enqueuing CHLD-like SIG$_[0] event";
84             }
85              
86 203         1035 $poe_kernel->_data_sig_enqueue_poll_event($_[0]);
87             }
88              
89             #------------------------------------------------------------------------------
90             # Signal handler maintenance functions.
91              
92             sub loop_watch_signal {
93 257     220 0 1052 my ($self, $signal) = @_;
94              
95 220         776 $signal_watched{$signal} = 1;
96              
97             # Child process has stopped.
98 220 100 66     936 if ($signal eq 'CHLD' or $signal eq 'CLD') {
99 204         275 if ( USE_SIGCHLD ) {
100             # Poll once for signals. Will set the signal handler when done.
101             # It would be more efficient to set $SIG{$signal} here and reap
102             # processes, but that would synchronously set the signal
103             # handler, and subsequent system() calls within the callback
104             # could fail with a -1 return value. The polling event defers
105             # the setup until the current callback returns.
106 204         1642 $self->_data_sig_enqueue_poll_event($signal);
107             } else {
108             # We should never twiddle $SIG{CH?LD} under POE, unless we want to
109             # override system() and friends. --hachi
110             # $SIG{$signal} = "DEFAULT";
111             $self->_data_sig_begin_polling($signal);
112             }
113 204         555 return;
114             }
115              
116             # Broken pipe.
117 16 100       47 if ($signal eq 'PIPE') {
118 4         27 $SIG{$signal} = \&_loop_signal_handler_pipe;
119 4         11 return;
120             }
121              
122             # Everything else.
123 12         148 $SIG{$signal} = \&_loop_signal_handler_generic;
124             }
125              
126             sub loop_ignore_signal {
127 7455     7455 0 8629 my ($self, $signal) = @_;
128              
129 7455         7395 delete $signal_watched{$signal};
130              
131 7455 100 100     26638 if ($signal eq 'CHLD' or $signal eq 'CLD') {
132 1091         1096 if ( USE_SIGCHLD ) {
133 1091 100       3002 if ($self->_data_sig_kernel_awaits_pids()) {
134             # We need SIGCHLD to stay around after shutdown, so that
135             # child processes may be reaped and kr_child_procs=0
136 7         14 if (TRACE_SIGNALS) {
137             POE::Kernel::_warn " Keeping SIG$signal anyway!";
138             }
139 34         28 return;
140             }
141             } else {
142             $self->_data_sig_cease_polling();
143             # We should never twiddle $SIG{CH?LD} under poe, unless we want to
144             # override system() and friends. --hachi
145             # $SIG{$signal} = "IGNORE";
146             return;
147             }
148             }
149              
150 4161         3494 delete $signal_watched{$signal};
151              
152 7448         6720 my $state = 'DEFAULT';
153 7417 100       9891 if ($signal eq 'PIPE') {
154 3570         5579 $state = "IGNORE";
155             }
156              
157 4371         3194 if (TRACE_SIGNALS) {
158             POE::Kernel::_warn " $state SIG$signal";
159             }
160 7415         21761 $SIG{$signal} = $state;
161             }
162              
163             sub loop_ignore_all_signals {
164 3477     190 0 8973 my $self = shift;
165 3477         37283 foreach my $signal (keys %signal_watched) {
166 0           $self->loop_ignore_signal($signal);
167             }
168             }
169              
170             1;
171              
172             __END__