在Mojolicious中使用AnyEvent run_cmd,我不断收到此错误:"AnyEvent :: CondVar:递归阻塞等待尝试"

Her*_*rad 5 perl asynchronous mojolicious anyevent

在一个Mojolicious应用程序中,我正在尝试在单击链接时将ODT文件转换为HTML.我使用shell命令"soffice"转换文件.转换文件需要一些时间.我向用户发送状态消息以通知他进度.我通过写入Mojo :: Log对象发送这些状态更新消息.然后,我在EventSource路由中订阅此日志对象.

然后我遍历文件并使用AnyEvent :: Util run_cmd来执行外部"soffice"程序.

for my $file (@{ $filelist }) {
   my $output_dir = './output_dir';
   my $cmd = "soffice --headless --convert-to html --outdir '$output_dir' '$file'";
   my $cv = AnyEvent->condvar;
   my $w;
   $w = run_cmd($cmd, 
                '>'  => sub { my $out = shift;
                              &WriteToLog({ status => "cmd output '$out'..." });
                              undef $w;
                              $cv->send;
                 },

                '2>' => sub { my $err = shift;
                              &WriteToLog({ status => "ERROR '$err'..." });
                              undef $w;
                              $cv->send;
                 }
            );

   $cv->recv;
}
Run Code Online (Sandbox Code Playgroud)

几乎从主要的AnyEvent教程中复制和粘贴.如果只有很少的文件要转换(大约2或3),那么一切顺利.通过EventSource连接发送的状态消息显示在客户端浏览器上.然后在转换完所有文件后,将呈现网页.

如果要处理更多文件,则会转换一些文件,然后会出现线程标题中的错误消息.

包含上述代码的路由的路由是:

my $initdocs = $r->under->to('docroute#initdocs');
$initdocs->get('/showdocs')->to('docroute#showdocs');
Run Code Online (Sandbox Code Playgroud)

上面的代码是在"initdocs"路径中.

任何帮助表示赞赏.提前致谢.

Ale*_*ape 3

使用 AnyEvent 创建单线程服务器

AnyEvent 递归阻塞..

如果您使用 AnyEvent,则通常必须处理 CondVars。您可以使用 CondVar 做两件事:要么注册一个回调,该回调将在触发 CondVar 时调用,要么调用 recv,它将阻塞直到触发 CondVar。在 Mojo::Controller 的路由中,您可能想要阻塞,直到获得要向用户显示的所有数据。

以下面(虚构的)使用 CondVar 的示例为例:

未经测试:

get '/' => sub {
    ...
    my $cv = AnyEvent->condvar;
    my $timer = AnyEvent->timer(after => 1, cb => sub { $cv->send(1) });
    my $result = $cv->recv;
    ...
};
Run Code Online (Sandbox Code Playgroud)

您将收到一个运行时错误,指出“AnyEvent::CondVar: 检测到递归阻塞等待”。也许这是因为 Morbo 还使用 CondVar 作为 exit_guard,以无限长时间运行(在 CondVar 上阻塞是运行主循环的简单方法)。

我的方法是使用特定的事件循环,例如EV,并调用 EV->loop 而不是在 CondVar 上阻塞:

EV->loop
Run Code Online (Sandbox Code Playgroud)