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 88     88   1790 use strict;
  88         164  
  88         2341  
9 88     88   537 use warnings;
  88         181  
  88         3527  
10              
11             our $VERSION = '0.802';
12 88     88   469 use constant API_VERSION => '0.49';
  88         382  
  88         5921  
13              
14 88     88   481 use base qw( IO::Async::Loop );
  88         156  
  88         15345  
15              
16 88     88   582 use Carp;
  88         182  
  88         4997  
17              
18 88     88   35780 use IO::Poll qw( POLLIN POLLOUT POLLPRI POLLHUP POLLERR );
  88         340745  
  88         5553  
19              
20 88     88   995 use Errno qw( EINTR );
  88         1291  
  88         7169  
21 88     88   488 use Fcntl qw( S_ISREG );
  88         467  
  88         4794  
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 88   33 88   517 ( $^O eq "freebsd" and do { no warnings 'numeric'; (POSIX::uname)[2] >= 8.0 } );
  88     88   308  
  88         4850  
  88         535  
  88         187  
  88         6529  
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 88     88   534 use constant FAKE_ISREG_READY => IO::Async::OS->HAVE_FAKE_ISREG_READY;
  88         139  
  88         5479  
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 88     88   496 use constant POLL_CONNECT_POLLPRI => IO::Async::OS->HAVE_POLL_CONNECT_POLLPRI;
  88         215  
  88         4644  
35              
36 88     88   483 use constant _CAN_WATCHDOG => 1;
  88         193  
  88         4377  
37 88     88   494 use constant WATCHDOG_ENABLE => IO::Async::Loop->WATCHDOG_ENABLE;
  88         179  
  88         90982  
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 87     87 1 247 my $class = shift;
122 87         208 my ( %args ) = @_;
123              
124 87         206 my $poll = delete $args{poll};
125              
126 87         755 my $self = $class->__new( %args );
127              
128 87         203 $self->{poll} = $poll;
129 87         167 $self->{pollmask} = {};
130              
131 87         744 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 1199     1199 1 4845 my $self = shift;
153              
154 1199         2430 my $iowatches = $self->{iowatches};
155 1199         2179 my $poll = $self->{poll};
156              
157 1199         1865 my $count = 0;
158              
159 1199         1773 alarm( IO::Async::Loop->WATCHDOG_INTERVAL ) if WATCHDOG_ENABLE;
160              
161 1199         6338 foreach my $fd ( keys %$iowatches ) {
162 2569 100       6801 my $watch = $iowatches->{$fd} or next;
163              
164             my $events = $poll ? $poll->events( $watch->[0] )
165 2568 100       6297 : $self->{pollevents}{$fd};
166 2568         3299 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 2568 100       5700 if( $events & (POLLIN|POLLHUP|POLLERR) ) {
173 1285 100       23452 $count++, $watch->[1]->() if defined $watch->[1];
174             }
175              
176 2568 100       6239 if( $events & (POLLOUT|POLLPRI|POLLHUP|POLLERR) ) {
177 754 100       2316 $count++, $watch->[2]->() if defined $watch->[2];
178             }
179              
180 2568 100       7503 if( $events & (POLLHUP|POLLERR) ) {
181 650 100       3299 $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 1199         5523 $count += $self->_manage_queues;
188              
189 1197         2081 alarm( 0 ) if WATCHDOG_ENABLE;
190              
191 1197         6370 return $count;
192             }
193              
194             sub is_running
195             {
196 1     1 0 3 my $self = shift;
197 1         9 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 1197     1197 1 14923 my $self = shift;
215 1197         2825 my ( $timeout ) = @_;
216              
217 1197         6243 $self->_adjust_timeout( \$timeout );
218              
219 1197         2163 $timeout = 0 if FAKE_ISREG_READY and keys %{ $self->{fake_isreg} };
220              
221             # Round up to nearest millisecond
222 1197 100       2868 if( $timeout ) {
223 1028         2301 my $mils = $timeout * 1000;
224 1028         2206 my $fraction = $mils - int $mils;
225 1028 100       2312 $timeout += ( 1 - $fraction ) / 1000 if $fraction;
226             }
227              
228 1197 50       3054 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 1197         1798 my @pollmasks = %{ $self->{pollmask} };
  1197         6119  
264              
265 1197         5610 $self->pre_wait;
266              
267             # Perl 5.8.x's IO::Poll::_poll gets confused with no masks
268 1197         24467 my $pollret;
269 1197 100       2596 if( @pollmasks ) {
270 1084 100       2633 my $msec = defined $timeout ? $timeout * 1000 : -1;
271 1084         194544244 $pollret = IO::Poll::_poll( $msec, @pollmasks );
272 1084 100 66     18512 if( $pollret == -1 and $! == EINTR or
      66        
      66        
273             $pollret == 0 and $self->{sigproxy} ) {
274 39         576 local $!;
275              
276 39         229 @pollmasks = %{ $self->{pollmask} };
  39         423  
277 39         585 my $secondattempt = IO::Poll::_poll( $msec, @pollmasks );
278 39 50       535 $pollret = $secondattempt if $secondattempt > 0;
279             }
280              
281             }
282             else {
283             # Workaround - we'll use select to fake a millisecond-accurate sleep
284 113         72089501 $pollret = select( undef, undef, undef, $timeout );
285             }
286              
287 1197         11843 $self->post_wait;
288              
289 1197 50       17293 return undef unless defined $pollret;
290              
291 1197         7946 $self->{pollevents} = { @pollmasks };
292 1197         4446 return $self->post_poll;
293             }
294             }
295              
296             sub watch_io
297             {
298 802     802 1 3299 my $self = shift;
299 802         5977 my %params = @_;
300              
301 802         8131 $self->__watch_io( %params );
302              
303 802         1728 my $poll = $self->{poll};
304              
305 802         1254 my $handle = $params{handle};
306 802         1785 my $fileno = $handle->fileno;
307              
308             my $curmask = $poll ? $poll->mask( $handle )
309 802 100       4363 : $self->{pollmask}{$fileno};
310 802   100     5410 $curmask ||= 0;
311              
312 802         1093 my $mask = $curmask;
313 802 100       2196 $params{on_read_ready} and $mask |= POLLIN;
314 802 100       1629 $params{on_write_ready} and $mask |= POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0);
315 802 100       1457 $params{on_hangup} and $mask |= POLLHUP;
316              
317 802         941 if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) {
318             $self->{fake_isreg}{$fileno} = $mask;
319             }
320              
321 802 100       1497 return if $mask == $curmask;
322              
323 801 100       1460 if( $poll ) {
324 4         9 $poll->mask( $handle, $mask );
325             }
326             else {
327 797         4812 $self->{pollmask}{$fileno} = $mask;
328             }
329             }
330              
331             sub unwatch_io
332             {
333 729     729 1 4727 my $self = shift;
334 729         2871 my %params = @_;
335              
336 729         4034 $self->__unwatch_io( %params );
337              
338 729         2107 my $poll = $self->{poll};
339              
340 729         1203 my $handle = $params{handle};
341 729         1486 my $fileno = $handle->fileno;
342              
343             my $curmask = $poll ? $poll->mask( $handle )
344 729 100       3888 : $self->{pollmask}{$fileno};
345 729   100     2828 $curmask ||= 0;
346              
347 729         1083 my $mask = $curmask;
348 729 100       1730 $params{on_read_ready} and $mask &= ~POLLIN;
349 729 100       1493 $params{on_write_ready} and $mask &= ~(POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0));
350 729 100       1496 $params{on_hangup} and $mask &= ~POLLHUP;
351              
352 729         907 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 729 100       1675 return if $mask == $curmask;
362              
363 694 100       1474 if( $poll ) {
364 3         7 $poll->mask( $handle, $mask );
365             }
366             else {
367             $mask ? ( $self->{pollmask}{$fileno} = $mask )
368 691 100       2919 : ( delete $self->{pollmask}{$fileno} );
369             }
370             }
371              
372             =head1 AUTHOR
373              
374             Paul Evans
375              
376             =cut
377              
378             0x55AA;