Subject: | do_request(on_error => sub {...}) leaks when there are more than max_connections_per_host attempts |
Attached is a script that leaks indefinitely. Every second it makes 6 requests on a Net::Async::HTTP object with max_connections_per_host set to 5. Every few seconds the memory goes up. (To see this happen faster, create 20 connections a second instead of 6).
If I load this up under Devel::MAT I see that there are many futures created and many Net::Async::HTTP::Ready/Net::Async::HTTP::Connection objects that are just lying around for some reason.
If I do:
my $old; my $count;
BEGIN { $old = \&Future::new; }
{
package Future;
sub new { $count++; return $old->(@_); }
DESTROY { $count--; warn "Count: $count\n"; }
}
I see $count climb a few times every second when we create 6 requests at a time. If we create <= 5 requests at a time, $count stays at 0 at the end of every cycle.
-- Matthew Horsfall (alh)
Subject: | leak2.pl |
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Request;
use IO::Async::Loop;
use IO::Async::Timer::Periodic;
use Net::Async::HTTP;
use Future;
my $loop = IO::Async::Loop->new;
my $timer = IO::Async::Timer::Periodic->new(
interval => 1,
first_interval => 0,
on_tick => \&work,
);
$timer->start;
$loop->add($timer);
$timer = IO::Async::Timer::Periodic->new(
interval => 60,
on_tick => sub { exit },
);
$timer->start;
$loop->add($timer);
my $http = Net::Async::HTTP->new(
max_connections_per_host => 5,
pipeline => 0,
);
$loop->add($http);
$loop->run;
sub work {
for (1..6) { # Stops leaking if we change this to 5
$http->do_request(
# I see 'connection refused' errors for localhost:10234
request => HTTP::Request->new('GET', 'http://127.0.0.1:10234'),
on_response => sub { warn "$$: Got response! @_\n"; },
on_error => sub { warn "$$: Got error: @_\n"; },
);
}
}