File Coverage

blib/lib/IO/Async/Loop/Poll.pm
Criterion Covered Total %
statement 130 142 91.5
branch 55 66 83.3
condition 11 25 44.0
subroutine 20 20 100.0
pod 5 6 83.3
total 221 259 85.3


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2007-2020 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::Poll;
7              
8 85     85   2680 use strict;
  85         200  
  85         2953  
9 85     85   489 use warnings;
  85         184  
  85         4415  
10              
11             our $VERSION = '0.79';
12 85     85   510 use constant API_VERSION => '0.49';
  85         203  
  85         7255  
13              
14 85     85   1191 use base qw( IO::Async::Loop );
  85         208  
  85         18694  
15              
16 85     85   589 use Carp;
  85         216  
  85         6153  
17              
18 85     85   45043 use IO::Poll qw( POLLIN POLLOUT POLLPRI POLLHUP POLLERR );
  85         425931  
  85         6709  
19              
20 85     85   1224 use Errno qw( EINTR );
  85         1552  
  85         8642  
21 85     85   553 use Fcntl qw( S_ISREG );
  85         189  
  85         5900  
22              
23             # Only Linux, or FreeBSD 8.0 and above, are known always to be able to report
24             # EOF conditions on filehandles using POLLHUP
25             use constant _CAN_ON_HANGUP =>
26             ( $^O eq "linux" ) ||
27 85   33 85   584 ( $^O eq "freebsd" and do { no warnings 'numeric'; (POSIX::uname)[2] >= 8.0 } );
  85     85   176  
  85         5877  
  85         545  
  85         195  
  85         7116  
28              
29             # poll() on most platforms claims that ISREG files are always read- and
30             # write-ready, but not on MSWin32. We need to fake this
31 85     85   648 use constant FAKE_ISREG_READY => IO::Async::OS->HAVE_FAKE_ISREG_READY;
  85         210  
  85         6777  
32             # poll() on most platforms indicates POLLOUT when connect() fails, but not on
33             # MSWin32. Have to poll also for POLLPRI in that case
34 85     85   564 use constant POLL_CONNECT_POLLPRI => IO::Async::OS->HAVE_POLL_CONNECT_POLLPRI;
  85         166  
  85         5558  
35              
36 85     85   665 use constant _CAN_WATCHDOG => 1;
  85         210  
  85         4883  
37 85     85   538 use constant WATCHDOG_ENABLE => IO::Async::Loop->WATCHDOG_ENABLE;
  85         225  
  85         106922  
38              
39             =head1 NAME
40              
41             C - use C with C
42              
43             =head1 SYNOPSIS
44              
45             Normally an instance of this class would not be directly constructed by a
46             program. It may however, be useful for runinng L with an existing
47             program already using an C object.
48              
49             use IO::Poll;
50             use IO::Async::Loop::Poll;
51              
52             my $poll = IO::Poll->new;
53             my $loop = IO::Async::Loop::Poll->new( poll => $poll );
54              
55             $loop->add( ... );
56              
57             while(1) {
58             my $timeout = ...
59             my $ret = $poll->poll( $timeout );
60             $loop->post_poll;
61             }
62              
63             =head1 DESCRIPTION
64              
65             This subclass of L uses the C system call to perform
66             read-ready and write-ready tests.
67              
68             By default, this loop will use the underlying C system call directly,
69             bypassing the usual L object wrapper around it because of a number
70             of bugs and design flaws in that class; namely
71              
72             =over 2
73              
74             =item *
75              
76             L - IO::Poll relies on
77             stable stringification of IO handles
78              
79             =item *
80              
81             L - IO::Poll->poll() with no
82             handles always returns immediately
83              
84             =back
85              
86             However, to integrate with existing code that uses an C object, a
87             C can be called immediately after the C method that
88             C object. The appropriate mask bits are maintained on the
89             C object when notifiers are added or removed from the loop, or when
90             they change their C status. The C method inspects the
91             result bits and invokes the C or C methods on
92             the notifiers.
93              
94             =cut
95              
96             =head1 CONSTRUCTOR
97              
98             =cut
99              
100             =head2 new
101              
102             $loop = IO::Async::Loop::Poll->new( %args )
103              
104             This function returns a new instance of a C object. It
105             takes the following named arguments:
106              
107             =over 8
108              
109             =item C
110              
111             The C object to use for notification. Optional; if a value is not
112             given, the underlying C function is invoked directly,
113             outside of the object wrapping.
114              
115             =back
116              
117             =cut
118              
119             sub new
120             {
121 84     84 1 319 my $class = shift;
122 84         235 my ( %args ) = @_;
123              
124 84         202 my $poll = delete $args{poll};
125              
126 84         814 my $self = $class->__new( %args );
127              
128 84         239 $self->{poll} = $poll;
129 84         215 $self->{pollmask} = {};
130              
131 84         933 return $self;
132             }
133              
134             =head1 METHODS
135              
136             =cut
137              
138             =head2 post_poll
139              
140             $count = $loop->post_poll
141              
142             This method checks the returned event list from a C call,
143             and calls any of the notification methods or callbacks that are appropriate.
144             It returns the total number of callbacks that were invoked; that is, the
145             total number of C and C callbacks for
146             C, and C event callbacks.
147              
148             =cut
149              
150             sub post_poll
151             {
152 1195     1195 1 5162 my $self = shift;
153              
154 1195         2948 my $iowatches = $self->{iowatches};
155 1195         3128 my $poll = $self->{poll};
156              
157 1195         2564 my $count = 0;
158              
159 1195         1958 alarm( IO::Async::Loop->WATCHDOG_INTERVAL ) if WATCHDOG_ENABLE;
160              
161 1195         7842 foreach my $fd ( keys %$iowatches ) {
162 2704 100       9214 my $watch = $iowatches->{$fd} or next;
163              
164             my $events = $poll ? $poll->events( $watch->[0] )
165 2703 100       7011 : $self->{pollevents}{$fd};
166 2703         3958 if( FAKE_ISREG_READY and $self->{fake_isreg}{$fd} ) {
167             $events |= $self->{fake_isreg}{$fd} & ( POLLIN|POLLOUT );
168             }
169              
170             # We have to test separately because kernel doesn't report POLLIN when
171             # a pipe gets closed.
172 2703 100       7212 if( $events & (POLLIN|POLLHUP|POLLERR) ) {
173 1262 100       6955 $count++, $watch->[1]->() if defined $watch->[1];
174             }
175              
176 2703 100       7459 if( $events & (POLLOUT|POLLPRI|POLLHUP|POLLERR) ) {
177 756 100       2757 $count++, $watch->[2]->() if defined $watch->[2];
178             }
179              
180 2703 100       8813 if( $events & (POLLHUP|POLLERR) ) {
181 667 100       4059 $count++, $watch->[3]->() if defined $watch->[3];
182             }
183             }
184              
185             # Since we have no way to know if the timeout occurred, we'll have to
186             # attempt to fire any waiting timeout events anyway
187 1195         6641 $count += $self->_manage_queues;
188              
189 1193         2141 alarm( 0 ) if WATCHDOG_ENABLE;
190              
191 1193         7707 return $count;
192             }
193              
194             sub is_running
195             {
196 1     1 0 5 my $self = shift;
197 1         433 return $self->{running};
198             }
199              
200             =head2 loop_once
201              
202             $count = $loop->loop_once( $timeout )
203              
204             This method calls the C method on the stored C object,
205             passing in the value of C<$timeout>, and then runs the C method
206             on itself. It returns the total number of callbacks invoked by the
207             C method, or C if the underlying C method returned
208             an error.
209              
210             =cut
211              
212             sub loop_once
213             {
214 1193     1193 1 16967 my $self = shift;
215 1193         3208 my ( $timeout ) = @_;
216              
217 1193         7064 $self->_adjust_timeout( \$timeout );
218              
219 1193         2549 $timeout = 0 if FAKE_ISREG_READY and keys %{ $self->{fake_isreg} };
220              
221             # Round up to nearest millisecond
222 1193 100       3438 if( $timeout ) {
223 1044         2486 my $mils = $timeout * 1000;
224 1044         3049 my $fraction = $mils - int $mils;
225 1044 100       2892 $timeout += ( 1 - $fraction ) / 1000 if $fraction;
226             }
227              
228 1193 50       3907 if( my $poll = $self->{poll} ) {
229 0         0 my $pollret;
230              
231 0         0 $self->pre_wait;
232             # There is a bug in IO::Poll at least version 0.07, where poll with no
233             # registered masks returns immediately, rather than waiting for a timeout
234             # This has been reported:
235             # http://rt.cpan.org/Ticket/Display.html?id=25049
236 0 0       0 if( $poll->handles ) {
237 0         0 $pollret = $poll->poll( $timeout );
238              
239 0 0 0     0 if( ( $pollret == -1 and $! == EINTR ) or $pollret == 0
      0        
      0        
240             and defined $self->{sigproxy} ) {
241             # A signal occurred and we have a sigproxy. Allow one more poll
242             # call with zero timeout. If it finds something, keep that result.
243             # If it finds nothing, keep -1
244              
245             # Preserve $! whatever happens
246 0         0 local $!;
247              
248 0         0 my $secondattempt = $poll->poll( 0 );
249 0 0       0 $pollret = $secondattempt if $secondattempt > 0;
250             }
251             }
252             else {
253             # Workaround - we'll use select to fake a millisecond-accurate sleep
254 0         0 $pollret = select( undef, undef, undef, $timeout );
255             }
256              
257 0         0 $self->post_wait;
258              
259 0 0       0 return undef unless defined $pollret;
260 0         0 return $self->post_poll;
261             }
262             else {
263 1193         2222 my @pollmasks = %{ $self->{pollmask} };
  1193         8314  
264              
265 1193         7224 $self->pre_wait;
266              
267             # Perl 5.8.x's IO::Poll::_poll gets confused with no masks
268 1193         29451 my $pollret;
269 1193 100       3586 if( @pollmasks ) {
270 1101 100       3298 my $msec = defined $timeout ? $timeout * 1000 : -1;
271 1101         223476605 $pollret = IO::Poll::_poll( $msec, @pollmasks );
272 1101 100 66     21288 if( $pollret == -1 and $! == EINTR or
      66        
      66        
273             $pollret == 0 and $self->{sigproxy} ) {
274 32         572 local $!;
275              
276 32         218 @pollmasks = %{ $self->{pollmask} };
  32         417  
277 32         650 my $secondattempt = IO::Poll::_poll( $msec, @pollmasks );
278 32 50       729 $pollret = $secondattempt if $secondattempt > 0;
279             }
280              
281             }
282             else {
283             # Workaround - we'll use select to fake a millisecond-accurate sleep
284 92         63085635 $pollret = select( undef, undef, undef, $timeout );
285             }
286              
287 1193         12534 $self->post_wait;
288              
289 1193 50       19311 return undef unless defined $pollret;
290              
291 1193         9801 $self->{pollevents} = { @pollmasks };
292 1193         5694 return $self->post_poll;
293             }
294             }
295              
296             sub watch_io
297             {
298 773     773 1 3442 my $self = shift;
299 773         6923 my %params = @_;
300              
301 773         8542 $self->__watch_io( %params );
302              
303 773         1969 my $poll = $self->{poll};
304              
305 773         1418 my $handle = $params{handle};
306 773         2173 my $fileno = $handle->fileno;
307              
308             my $curmask = $poll ? $poll->mask( $handle )
309 773 100       4945 : $self->{pollmask}{$fileno};
310 773   100     6957 $curmask ||= 0;
311              
312 773         1325 my $mask = $curmask;
313 773 100       2342 $params{on_read_ready} and $mask |= POLLIN;
314 773 100       1849 $params{on_write_ready} and $mask |= POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0);
315 773 100       1743 $params{on_hangup} and $mask |= POLLHUP;
316              
317 773         1212 if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) {
318             $self->{fake_isreg}{$fileno} = $mask;
319             }
320              
321 773 100       2247 return if $mask == $curmask;
322              
323 772 100       1778 if( $poll ) {
324 4         11 $poll->mask( $handle, $mask );
325             }
326             else {
327 768         5295 $self->{pollmask}{$fileno} = $mask;
328             }
329             }
330              
331             sub unwatch_io
332             {
333 702     702 1 4386 my $self = shift;
334 702         3180 my %params = @_;
335              
336 702         4549 $self->__unwatch_io( %params );
337              
338 702         2154 my $poll = $self->{poll};
339              
340 702         1335 my $handle = $params{handle};
341 702         1634 my $fileno = $handle->fileno;
342              
343             my $curmask = $poll ? $poll->mask( $handle )
344 702 100       4393 : $self->{pollmask}{$fileno};
345 702   100     2070 $curmask ||= 0;
346              
347 702         1259 my $mask = $curmask;
348 702 100       2668 $params{on_read_ready} and $mask &= ~POLLIN;
349 702 100       2144 $params{on_write_ready} and $mask &= ~(POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0));
350 702 100       2016 $params{on_hangup} and $mask &= ~POLLHUP;
351              
352 702         1215 if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) {
353             if( $mask ) {
354             $self->{fake_isreg}{$handle->fileno} = $mask;
355             }
356             else {
357             delete $self->{fake_isreg}{$handle->fileno};
358             }
359             }
360              
361 702 100       1864 return if $mask == $curmask;
362              
363 667 100       1672 if( $poll ) {
364 3         9 $poll->mask( $handle, $mask );
365             }
366             else {
367             $mask ? ( $self->{pollmask}{$fileno} = $mask )
368 664 100       6723 : ( delete $self->{pollmask}{$fileno} );
369             }
370             }
371              
372             =head1 AUTHOR
373              
374             Paul Evans
375              
376             =cut
377              
378             0x55AA;