【问题标题】:mojolicious script works three times, then crashesmojolicious 脚本工作了三遍,然后崩溃
【发布时间】:2013-04-08 14:45:50
【问题描述】:

以下脚本应该演示我在使用 mod_perl 在 OpenBSD5.2 上使用 Mojolicious 时遇到的问题。

脚本在 mod_perl 下作为 CGI 调用了 4 次,运行良好。脚本的额外运行导致 Mojolicious 不返回异步帖子。通常在数据到达时调用的 subs 似乎不再被调用。从命令行运行脚本工作正常,因为 perl 完全从头开始,一切都重新初始化,而 mod_perl 下不是这种情况。停止和启动 Apache 会重新初始化 mod_perl,以便脚本可以再运行 4 次。

我仅在 OpenBSDs 端口树 (2.76) 中提供的版本中使用 Mojolicious 在 OpenBSD5.2 上对此进行了测试。我认为这有点老了,但这就是 OpenBSD 附带的。

我在这里做错了吗?或者 Mojolicious 有可能有一些循环引用或导致这个问题的东西?

我对所使用的平台 (OpenBSD) 没有任何影响。所以请不要建议“使用 Linux 并安装最新的 Mojolicious 版本”。但是,如果您确定运行更高版本的 Mojolicous 会解决问题,我可能会获得安装它的许可(尽管我还不知道如何安装)。

提前致谢!

T.

这是脚本:

#!/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;

【问题讨论】:

    标签: perl mod-perl mojolicious openbsd


    【解决方案1】:

    好吧,我不想这么说,但这里有很多错误。最明显的是您对... for $delay->wait 的使用,这没有多大意义。此外,您正在将数字与ne 而不是!= 进行比较。不是my-ing 更深回调中的参数对于异步样式代码似乎有问题。

    然后会有一些代码异味,例如对 url 进行正则表达式并不必要地关闭 $md5 变量。

    最后,既然 Mojolicious 可以在 CGI 下正常运行,为什么还要使用 CGI.pm?当你这样做时,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;
    

    【讨论】:

    • 感谢您对我的代码有什么问题的每一条评论! delay->wait -> 不知道,我从一个示例中复制了它,我认为这将是某种等待异步 subs 完成的循环。我承认我没看懂。该脚本的目标是向各种来源发出 4 或 5 个 http-request(post 和 get),并在所有来源都响应后开始解析结果,然后返回最终结果。我的示例代码只是我脚本的摘录,显示了我在 mod_perl 下使用该脚本时遇到的问题。
    • 关于资源:任何 MS Windows 系统文件的任何 MD5 都可以。例如 10e4a1d2132ccb5c6759f038cdb6f3c9 (calc.exe)。
    • 我只有几分钟的时间来尝试您建议的代码。然而我无法让它工作,我可能需要更深入地挖掘原因,它返回“状态:404 Not Found”,虽然我第一眼看不到那里可能有什么问题。
    • 这几天我可能没有太多时间来做这件事,我离提交博士论文只有几天了。如果您有特定的问题,我很乐意提供帮助,但我可能已经在这个示例上花费了比我应该花更多的时间 :-)
    • 我无法在 mod_perl 和 Apache 下运行代码,但使用 morbo 运行良好。所以我认为问题不在我的脚本中,但这个(旧)版本的 Mojolicious 和 mod_perl 存在一些一般性问题。看来我将不得不尝试在 OpenBSD 上运行最新版本的 mojolicious。
    猜你喜欢
    • 2012-07-05
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    相关资源
    最近更新 更多