Skip Menu |

This queue is for tickets about the IO-Async CPAN distribution.

Report information
The Basics
Id: 66168
Status: resolved
Priority: 0/
Queue: IO-Async

People
Owner: Nobody in particular
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.39
Fixed in: 0.40



Subject: $loop->listen leaks Listener notifier if $listener->listen fails
$loop->listen creates a Listener object, ->adds it, then calls $listener- Show quoted text
>listen. If the listener object fails, it ought to ->remove from the loop
again. Currently it does not. This is achievable by wrapping the 'on_listen_error' continuation, and possibly others. -- Paul Evans
Patch attached. -- Paul Evans
Subject: rt66168.patch
=== modified file 'lib/IO/Async/Loop.pm' --- lib/IO/Async/Loop.pm 2011-02-24 13:20:40 +0000 +++ lib/IO/Async/Loop.pm 2011-03-02 18:32:19 +0000 @@ -1048,8 +1048,19 @@ $on_listen->( $listener->read_handle ) if $on_listen; $on_notifier->( $listener ) if $on_notifier; }, + on_listen_error => sub { + $self->remove( $listener ); + $params{on_listen_error}->( @_ ) if $params{on_listen_error}; + }, + on_resolve_error => sub { + $self->remove( $listener ); + $params{on_resolve_error}->( @_ ) if $params{on_resolve_error}; + }, ); } + + # Unit testing needs this + return $listener; } =head1 OS ABSTRACTIONS === modified file 't/52loop-listen.t' --- t/52loop-listen.t 2011-03-02 18:22:02 +0000 +++ t/52loop-listen.t 2011-03-02 18:32:19 +0000 @@ -4,7 +4,7 @@ use IO::Async::Test; -use Test::More tests => 17; +use Test::More tests => 19; use IO::Socket::INET; @@ -137,14 +137,15 @@ } SKIP: { - skip "No bind()-failing ports found", 4 unless defined $badport; + skip "No bind()-failing ports found", 6 unless defined $badport; my $failop; my $failerr; my @error; - $loop->listen( + # Undocumented API, returning the Listener object + my $listener = $loop->listen( family => "inet", socktype => "stream", host => "localhost", @@ -167,4 +168,7 @@ is( $error[0], "bind", '$error[0] is bind' ); is( "$error[1]", $failure, "\$error[1] is '$failure'" ); + + ok( defined $listener, '$listener defined after bind failure' ); + ok( !$listener->get_loop, '$listener not in loop after bind failure' ); }