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   2413 use strict;
  88         565  
  88         2956  
9 88     88   496 use warnings;
  88         197  
  88         4119  
10              
11             our $VERSION = '0.801';
12 88     88   530 use constant API_VERSION => '0.49';
  88         261  
  88         6938  
13              
14 88     88   854 use base qw( IO::Async::Loop );
  88         225  
  88         18180  
15              
16 88     88   614 use Carp;
  88         166  
  88         6100  
17              
18 88     88   44093 use IO::Poll qw( POLLIN POLLOUT POLLPRI POLLHUP POLLERR );
  88         418948  
  88         6797  
19              
20 88     88   1252 use Errno qw( EINTR );
  88         1686  
  88         8282  
21 88     88   650 use Fcntl qw( S_ISREG );
  88         199  
  88         5523  
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   628 ( $^O eq "freebsd" and do { no warnings 'numeric'; (POSIX::uname)[2] >= 8.0 } );
  88     88   202  
  88         5575  
  88         583  
  88         201  
  88         7248  
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   664 use constant FAKE_ISREG_READY => IO::Async::OS->HAVE_FAKE_ISREG_READY;
  88         264  
  88         6562  
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   596 use constant POLL_CONNECT_POLLPRI => IO::Async::OS->HAVE_POLL_CONNECT_POLLPRI;
  88         185  
  88         6012  
35              
36 88     88   621 use constant _CAN_WATCHDOG => 1;
  88         187  
  88         5354  
37 88     88   600 use constant WATCHDOG_ENABLE => IO::Async::Loop->WATCHDOG_ENABLE;
  88         209  
  88         111122  
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 337 my $class = shift;
122 87         224 my ( %args ) = @_;
123              
124 87         223 my $poll = delete $args{poll};
125              
126 87         752 my $self = $class->__new( %args );
127              
128 87         233 $self->{poll} = $poll;
129 87         229 $self->{pollmask} = {};
130              
131 87         842 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 1271     1271 1 5574 my $self = shift;
153              
154 1271         3064 my $iowatches = $self->{iowatches};
155 1271         2889 my $poll = $self->{poll};
156              
157 1271         2595 my $count = 0;
158              
159 1271         2098 alarm( IO::Async::Loop->WATCHDOG_INTERVAL ) if WATCHDOG_ENABLE;
160              
161 1271         8360 foreach my $fd ( keys %$iowatches ) {
162 2772 100       9091 my $watch = $iowatches->{$fd} or next;
163              
164             my $events = $poll ? $poll->events( $watch->[0] )
165 2771 100       6859 : $self->{pollevents}{$fd};
166 2771         3754 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 2771 100       6284 if( $events & (POLLIN|POLLHUP|POLLERR) ) {
173 1289 100       7425 $count++, $watch->[1]->() if defined $watch->[1];
174             }
175              
176 2771 100       7461 if( $events & (POLLOUT|POLLPRI|POLLHUP|POLLERR) ) {
177 760 100       2586 $count++, $watch->[2]->() if defined $watch->[2];
178             }
179              
180 2771 100       9357 if( $events & (POLLHUP|POLLERR) ) {
181 656 100       3984 $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 1271         7020 $count += $self->_manage_queues;
188              
189 1269         2283 alarm( 0 ) if WATCHDOG_ENABLE;
190              
191 1269         7428 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 1269     1269 1 17073 my $self = shift;
215 1269         3055 my ( $timeout ) = @_;
216              
217 1269         9626 $self->_adjust_timeout( \$timeout );
218              
219 1269         2581 $timeout = 0 if FAKE_ISREG_READY and keys %{ $self->{fake_isreg} };
220              
221             # Round up to nearest millisecond
222 1269 100       3226 if( $timeout ) {
223 1105         2867 my $mils = $timeout * 1000;
224 1105         2822 my $fraction = $mils - int $mils;
225 1105 100       3192 $timeout += ( 1 - $fraction ) / 1000 if $fraction;
226             }
227              
228 1269 50       4095 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 1269         2294 my @pollmasks = %{ $self->{pollmask} };
  1269         8661  
264              
265 1269         6791 $self->pre_wait;
266              
267             # Perl 5.8.x's IO::Poll::_poll gets confused with no masks
268 1269         29730 my $pollret;
269 1269 100       3629 if( @pollmasks ) {
270 1156 100       3125 my $msec = defined $timeout ? $timeout * 1000 : -1;
271 1156         230722708 $pollret = IO::Poll::_poll( $msec, @pollmasks );
272 1156 100 66     23913 if( $pollret == -1 and $! == EINTR or
      66        
      66        
273             $pollret == 0 and $self->{sigproxy} ) {
274 39         620 local $!;
275              
276 39         238 @pollmasks = %{ $self->{pollmask} };
  39         549  
277 39         773 my $secondattempt = IO::Poll::_poll( $msec, @pollmasks );
278 39 50       514 $pollret = $secondattempt if $secondattempt > 0;
279             }
280              
281             }
282             else {
283             # Workaround - we'll use select to fake a millisecond-accurate sleep
284 113         72076087 $pollret = select( undef, undef, undef, $timeout );
285             }
286              
287 1269         13708 $self->post_wait;
288              
289 1269 50       20614 return undef unless defined $pollret;
290              
291 1269         11042 $self->{pollevents} = { @pollmasks };
292 1269         6421 return $self->post_poll;
293             }
294             }
295              
296             sub watch_io
297             {
298 802     802 1 3720 my $self = shift;
299 802         7220 my %params = @_;
300              
301 802         9159 $self->__watch_io( %params );
302              
303 802         2109 my $poll = $self->{poll};
304              
305 802         1557 my $handle = $params{handle};
306 802         2043 my $fileno = $handle->fileno;
307              
308             my $curmask = $poll ? $poll->mask( $handle )
309 802 100       5145 : $self->{pollmask}{$fileno};
310 802   100     6244 $curmask ||= 0;
311              
312 802         1359 my $mask = $curmask;
313 802 100       2335 $params{on_read_ready} and $mask |= POLLIN;
314 802 100       2242 $params{on_write_ready} and $mask |= POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0);
315 802 100       1908 $params{on_hangup} and $mask |= POLLHUP;
316              
317 802         1189 if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) {
318             $self->{fake_isreg}{$fileno} = $mask;
319             }
320              
321 802 100       1968 return if $mask == $curmask;
322              
323 801 100       1873 if( $poll ) {
324 4         11 $poll->mask( $handle, $mask );
325             }
326             else {
327 797         5359 $self->{pollmask}{$fileno} = $mask;
328             }
329             }
330              
331             sub unwatch_io
332             {
333 729     729 1 5723 my $self = shift;
334 729         3519 my %params = @_;
335              
336 729         4549 $self->__unwatch_io( %params );
337              
338 729         1960 my $poll = $self->{poll};
339              
340 729         1364 my $handle = $params{handle};
341 729         1716 my $fileno = $handle->fileno;
342              
343             my $curmask = $poll ? $poll->mask( $handle )
344 729 100       4700 : $self->{pollmask}{$fileno};
345 729   100     2141 $curmask ||= 0;
346              
347 729         1184 my $mask = $curmask;
348 729 100       2105 $params{on_read_ready} and $mask &= ~POLLIN;
349 729 100       1806 $params{on_write_ready} and $mask &= ~(POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0));
350 729 100       2843 $params{on_hangup} and $mask &= ~POLLHUP;
351              
352 729         1282 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       2101 return if $mask == $curmask;
362              
363 694 100       1623 if( $poll ) {
364 3         8 $poll->mask( $handle, $mask );
365             }
366             else {
367             $mask ? ( $self->{pollmask}{$fileno} = $mask )
368 691 100       3457 : ( delete $self->{pollmask}{$fileno} );
369             }
370             }
371              
372             =head1 AUTHOR
373              
374             Paul Evans
375              
376             =cut
377              
378             0x55AA;