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 175     175   896 use strict;
  175         276  
  175         7765  
9              
10 175     175   883 use vars qw($VERSION);
  175         267  
  175         12288  
11             $VERSION = '1.367'; # NOTE - Should be #.### (three decimal places)
12              
13             # Everything plugs into POE::Kernel.
14             package POE::Kernel;
15              
16 175     175   949 use strict;
  175         283  
  175         4726  
17 175     175   2667 use POE::Kernel;
  175         292  
  175         1687  
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   480 if( USE_SIGNAL_PIPE ) {
28 16         158 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         89 $poe_kernel, $poe_kernel, EN_SIGNAL, ET_SIGNAL, [ $_[0] ],
42             __FILE__, __LINE__, undef
43             );
44 16         437 $SIG{$_[0]} = \&_loop_signal_handler_generic;
45             }
46              
47             ##
48              
49             sub _loop_signal_handler_pipe {
50 28     12   385 if( USE_SIGNAL_PIPE ) {
51 12         62 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   18 if (TRACE_SIGNALS) {
60             POE::Kernel::_warn " Enqueuing PIPE-like SIG$_[0] event";
61             }
62              
63             $poe_kernel->_data_ev_enqueue(
64 12         58 $poe_kernel, $poe_kernel, EN_SIGNAL, ET_SIGNAL, [ $_[0] ],
65             __FILE__, __LINE__, undef
66             );
67 12         105 $SIG{$_[0]} = \&_loop_signal_handler_pipe;
68             }
69              
70             ## only used under USE_SIGCHLD
71              
72             sub _loop_signal_handler_chld {
73 220     208   20386 if( USE_SIGNAL_PIPE ) {
74 208         2916 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 208     208   275 if (TRACE_SIGNALS) {
83             POE::Kernel::_warn " Enqueuing CHLD-like SIG$_[0] event";
84             }
85              
86 208         1191 $poe_kernel->_data_sig_enqueue_poll_event($_[0]);
87             }
88              
89             #------------------------------------------------------------------------------
90             # Signal handler maintenance functions.
91              
92             sub loop_watch_signal {
93 261     219 0 993 my ($self, $signal) = @_;
94              
95 219         654 $signal_watched{$signal} = 1;
96              
97             # Child process has stopped.
98 219 100 66     2272 if ($signal eq 'CHLD' or $signal eq 'CLD') {
99 203         297 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 203         2074 $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 203         898 return;
114             }
115              
116             # Broken pipe.
117 16 100       52 if ($signal eq 'PIPE') {
118 4         31 $SIG{$signal} = \&_loop_signal_handler_pipe;
119 4         13 return;
120             }
121              
122             # Everything else.
123 12         162 $SIG{$signal} = \&_loop_signal_handler_generic;
124             }
125              
126             sub loop_ignore_signal {
127 7452     7452 0 11937 my ($self, $signal) = @_;
128              
129 7452         8956 delete $signal_watched{$signal};
130              
131 7452 100 100     30926 if ($signal eq 'CHLD' or $signal eq 'CLD') {
132 1089         1281 if ( USE_SIGCHLD ) {
133 1089 100       4181 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         17 if (TRACE_SIGNALS) {
137             POE::Kernel::_warn " Keeping SIG$signal anyway!";
138             }
139 34         30 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         5011 delete $signal_watched{$signal};
151              
152 7445         7618 my $state = 'DEFAULT';
153 7414 100       10209 if ($signal eq 'PIPE') {
154 3567         6169 $state = "IGNORE";
155             }
156              
157 4370         3634 if (TRACE_SIGNALS) {
158             POE::Kernel::_warn " $state SIG$signal";
159             }
160 7412         26620 $SIG{$signal} = $state;
161             }
162              
163             sub loop_ignore_all_signals {
164 3474     190 0 9395 my $self = shift;
165 3474         42172 foreach my $signal (keys %signal_watched) {
166 0           $self->loop_ignore_signal($signal);
167             }
168             }
169              
170             1;
171              
172             __END__