Skip Menu |

This queue is for tickets about the IO CPAN distribution.

Report information
The Basics
Id: 53677
Status: resolved
Priority: 0/
Queue: IO

People
Owner: Nobody in particular
Requestors: OHA [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: mask() skip closed handles also if removing
The mask() do not process IO::Handle which have no fileno. That must not be done when the mask is called for remove cauz if a handle is added to the Poll and then get closed, it is not possible to remove it from the poll. actually i just fixed the caller as follow: $poll->remove($io); delete $poll->[2]{$io} unless $io->fileno;
On Thu Jan 14 03:56:07 2010, OHA wrote: Show quoted text
> The mask() do not process IO::Handle which have no fileno. > > That must not be done when the mask is called for remove cauz if a > handle is added to the Poll and then get closed, it is not possible to > remove it from the poll. > > actually i just fixed the caller as follow: > > $poll->remove($io); > delete $poll->[2]{$io} unless $io->fileno;
A little fragile as it still leaves the entry in the $poll->[0] tree. Find attached a proper patch + regression test. -- Paul Evans
Subject: rt53677.patch
=== modified file 'lib/IO/Poll.pm' --- lib/IO/Poll.pm 2014-02-20 18:01:49 +0000 +++ lib/IO/Poll.pm 2014-02-20 18:11:45 +0000 @@ -47,20 +47,24 @@ my $self = shift; my $io = shift; my $fd = fileno($io); - return unless defined $fd; if (@_) { my $mask = shift; if($mask) { + return unless defined $fd; $self->[0]{$fd}{refaddr $io} = $mask; # the error events are always returned $self->[1]{$fd} = 0; # output mask $self->[2]{refaddr $io} = $io; # remember handle } else { - delete $self->[0]{$fd}{refaddr $io}; - unless(%{$self->[0]{$fd}}) { - # We no longer have any handles for this FD - delete $self->[1]{$fd}; - delete $self->[0]{$fd}; - } + # If ->remove'ing a closed filehandle, it now no longer has a fileno, so + # we'll have to search the long way round + foreach my $fd ( defined $fd ? ( $fd ) : keys %{$self->[0]} ) { + delete $self->[0]{$fd}{refaddr $io}; + unless(%{$self->[0]{$fd}}) { + # We no longer have any handles for this FD + delete $self->[1]{$fd}; + delete $self->[0]{$fd}; + } + } delete $self->[2]{refaddr $io}; } } === added file 't/rt53677.t' --- t/rt53677.t 1970-01-01 00:00:00 +0000 +++ t/rt53677.t 2014-02-20 18:11:45 +0000 @@ -0,0 +1,31 @@ +#!/usr/bin/perl + +# Regression test for https://rt.cpan.org/Ticket/Display.html?id=53677 + +use strict; +use warnings; + +use Test::More; + +use IO::Poll; + +use IO::Handle; + +pipe( my $rd, my $wr ) or die "Cannot pipe() - $!"; +$wr->syswrite( "data\n" ); + +my $poll = IO::Poll->new; +$poll->mask( $rd, POLLIN ); + +my $ret = $poll->poll( 0 ); +is( $ret, 1, 'poll() indicates 1 filehandle is ready' ); +is( $poll->events( $rd ), POLLIN, 'poll() indicates $rd has POLLIN' ); + +# close first, then remove afterwards +$rd->close; +$poll->remove( $rd ); + +$ret = $poll->poll( 0 ); +is( $ret, 0, 'poll() times out after remove' ); + +done_testing;
Ticket migrated to github as https://github.com/toddr/IO/issues/36