我正在使用Perl库HTTP::Async,如下所示:
use strict;
use warnings;
use HTTP::Async;
use Time::HiRes;
...
my $async = HTTP::Async->new( ... );
my $request = HTTP::Request->new( GET => $url );
my $start = [Time::HiRes::gettimeofday()];
my $id = $async->add($request);
my $response = undef;
while (!$response) {
$response = $async->wait_for_next_response(1);
last if Time::HiRes::tv_interval($start) > TIME_OUT;
}
...
当while
循环超时和脚本结束时,我遇到以下错误消息:
HTTP::Async object destroyed but still in use at script.pl line 0
HTTP::Async INTERNAL ERROR: 'id_opts' not empty at script.pl line 0
我有什么选择?如果仍在使用中,我如何“清理”HTTP :: Async对象,但不再需要它?
答案 0 :(得分:1)
我建议您remove
请求不完整,但模块不提供任何接口。
选项1 :添加删除功能。
将以下内容添加到您的脚本中:
BEGIN {
require HTTP::Async;
package HTTP::Async;
if (!defined(&remove)) {
*remove = sub {
my ($self, $id) = @_;
my $hashref = $self->{in_progress}{$id}
or return undef;
my $s = $hashref->{handle};
$self->_io_select->remove($s);
delete $self->{fileno_to_id}{ $s->fileno };
delete $self->{in_progress}{$id};
delete $self->{id_opts}{$id};
return $hashref->{request};
};
}
if (!defined(&remove_all)) {
*remove_all = sub {
my ($self) = @_;
return map $self->remove($_), keys %{ $self->{in_progress} };
};
}
}
您应该联系作者,看看他是否可以添加此功能。 $id
是add
返回的值。
选项2 :使析构函数中的所有警告静音。
如果您没有为所有请求提供服务,那么对警告进行静音是没有害处的。你可以这样做:
use Sub::ScopeFinalizer qw( scope_finalizer );
my $async = ...;
my $anchor = scope_finalizer {
local $SIG{__WARN__} = sub { };
$async = undef;
};
...
请注意,这会使对象破坏期间发生的所有警告静音,所以我不喜欢这样。
答案 1 :(得分:1)
将HTTP :: Async子类化为更通用的解决方案并不太难。我使用它来中止所有待处理的请求:
package HTTP::Async::WithFlush;
use strict;
use warnings;
use base 'HTTP::Async';
use Time::HiRes qw(time);
sub _flush_to_send {
my $self = shift;
for my $request (@{ $self->{to_send} }) {
delete $self->{id_opts}->{$request->[1]};
}
$self->{to_send} = [];
}
sub _flush_in_progress {
my $self = shift;
# cause all transfers to time out
for my $id (keys %{ $self->{in_progress} }) {
$self->{in_progress}->{$id}->{finish_by} = time - 1;
}
$self->_process_in_progress;
}
sub _flush_to_return {
my $self = shift;
while($self->_next_response(-1)) { }
}
sub flush_pending_requests {
my $self = shift;
$self->_flush_to_send;
$self->_flush_in_progress;
$self->_flush_to_return;
return;
}
1;
这可能比使用@ikegami的代码更容易使用模块内部。