mojolicious скрипт работает три раза, затем вылетает
Следующий скрипт должен продемонстрировать проблему, с которой я сталкиваюсь при использовании Mojolicious на OpenBSD5.2 с использованием mod_perl.
Скрипт работает 4 раза, вызываясь как CGI в mod_perl. Дополнительные запуски скрипта приводят к тому, что Mojolicious не возвращает асинхронные сообщения. Подпрограммы, которые обычно вызываются при поступлении данных, просто больше не вызываются. Запуск скрипта из командной строки работает нормально, так как тогда perl полностью запускается с нуля, и все инициализируется заново, что не относится к mod_perl. Остановка и запуск Apache повторно инициализирует mod_perl, чтобы скрипт мог быть запущен еще 4 раза.
Я проверял это только на OpenBSD5.2, используя Mojolicious в версии, которая представлена в дереве портов OpenBSD (2.76). Я думаю, что это довольно старое, но это то, с чем поставляется OpenBSD.
Я делаю что-то здесь не так? Или возможно, что у Mojolicious есть какая-то круговая ссылка или что-то, что вызывает эту проблему?
Я не имею никакого влияния на используемую платформу (OpenBSD). Поэтому, пожалуйста, не предлагайте "использовать Linux и установить последнюю версию Mojolicious". Однако, если вы уверены, что запуск более поздней версии Mojolicous решит проблему, я могу получить разрешение на ее установку (хотя я пока не знаю, как это сделать).
Заранее спасибо!
Т.
Вот сценарий:
#!/usr/bin/perl
use diagnostics;
use warnings;
use strict;
use feature qw(switch);
use CGI qw/:param/;
use CGI qw/:url/;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use Mojo::IOLoop;
use Mojo::JSON;
use Mojo::UserAgent;
my ($activeconnections, $md5, $cgi);
my $ua = Mojo::UserAgent->new;
$ua->max_redirects(0)->connect_timeout(3)->request_timeout(6); # Timeout 6 seconds of which 3 may be connecting
my $delay = Mojo::IOLoop->delay();
sub online{
my $url = "http://www.backgroundtask.eu/Systeemtaken/Search.php";
$delay->begin;
$activeconnections++;
my $response_bt = $ua->post_form($url, { 'ex' => $md5 }, sub {
my ($ua, $tx) = @_;
my $content=$tx->res->body;
$content =~ m/(http:\/\/www\.backgroundtask\.eu\/Systeemtaken\/taakinfo\/.*$md5\/)/;
if ($1){
print "getting $1\n";
my $response_bt2 = $ua->get($1, sub {
$delay->end();
$activeconnections--;
print "got result, ActiveConnections: $activeconnections\n";
($ua, $tx) = @_;
my $filename = $tx->res->dom->find('table.view')->[0]->find('tr.even')->[2]->td->[1]->all_text;
print "fn = " . $filename . "\n";
}
)
} else {
print "query did not return a result\n";
$activeconnections--;
$delay->end;
}
});
}
$cgi = new CGI;
print $cgi->header(-cache_control=>"no-cache, no-store, must-revalidate") . "\n";
$md5 = lc($cgi->param("md5") || ""); # read param
$md5 =~ s/[^a-f0-9]*//g if (length($md5) == 32); # custom input filter for md5 values only
if (length $md5 != 32) {
$md5=lc($ARGV[0]);
$md5=~ s/[^a-f0-9]*//g;
die "invalid MD5 $md5\n" if (length $md5 ne 32);
}
online;
if ($activeconnections) {
print "waiting..., activeconnections: $activeconnections\n" for $delay->wait;
}
print "all pending requests completed, activeconnections is " . $activeconnections . "\n";
print "script done.\n md5 was $md5\n";
exit 0;
1 ответ
Ну, я ненавижу это говорить, но здесь много чего не так. Наиболее ярким является ваше использование ... for $delay->wait
что не имеет особого смысла. Также вы сравниваете числа с ne
скорее, чем !=
, Не my
Определение аргументов в более глубоком обратном вызове кажется проблематичным для кода асинхронного стиля.
Затем есть некоторые запахи кода, такие как регулярное выражение для URL-адресов и закрытие над $md5
Переменная излишне.
И наконец, зачем использовать CGI.pm, когда Mojolicious может нормально работать под CGI? Когда вы делаете это, IOLoop уже работает, поэтому некоторые вещи становятся проще. И да, я понимаю, что вы используете систему, предоставленную Mojolicious, однако я чувствую, что должен упомянуть, что текущая версия 3.93:-)
В любом случае, вот пример, который убирает много вещей, но все же должен делать почти то же самое, что и пример. Конечно, я не могу проверить это без действительного md5 для сайта (и я также не могу избавиться от регулярного выражения url без примеров данных).
#!/usr/bin/perl
use Mojolicious::Lite;
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
$ua->max_redirects(0)->connect_timeout(3)->request_timeout(6); # Timeout 6 seconds of which 3 may be connecting
any '/' => sub {
my $self = shift;
$self->res->headers->cache_control("no-cache, no-store, must-revalidate");
my $md5 = lc($self->param("md5") || ""); # read param
$md5 =~ s/[^a-f0-9]*//g if (length($md5) == 32); # custom input filter for md5 values only
if (length $md5 != 32) {
$md5=lc($ARGV[0]);
$md5=~ s/[^a-f0-9]*//g;
die "invalid MD5 $md5\n" if (length $md5 != 32);
}
$self->render_later; # wait for ua
my $url = "http://www.backgroundtask.eu/Systeemtaken/Search.php";
$ua->post_form($url, { 'ex' => $md5 }, sub {
my ($ua, $tx) = @_;
my $content=$tx->res->body;
$content =~ m{(http://www\.backgroundtask\.eu/Systeemtaken/taakinfo/.*$md5/)};
return $self->render( text => 'Failed' ) unless $1;
$ua->get($1, sub {
my ($ua, $tx) = @_;
my $filename = $tx->res->dom->find('table.view')->[0]->find('tr.even')->[2]->td->[1]->all_text;
$self->render( text => "md5 was $md5, filename was $filename" );
});
});
};
app->start;