![](/img/trans.png)
[英]Perl Parallel::ForkManager , takes long time with fork condition changed
[英]Perl, Parallel::ForkManager - how to implement timeout for fork
是否可以使用Parallel :: ForkManager为fork实现某种超时(时间限制)?
Basic Parallel :: ForkManager脚本如下所示
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new( 10 );
for ( 1 .. 1000 ) {
$pm->start and next;
# some job for fork
$pm->finish;
}
$pm->wait_all_children();
我想限制“#for work for fork”的时间。 例如,如果它没有在90秒内完成。 那么它(fork)应该被杀死/终止。 我想过使用它,但我不得不说,我不知道如何在Parallel :: ForkManager中使用它。
感谢hobbs和ikegami。 你的建议都有效.....但只是在这个基本的例子中,而不是在我的实际脚本中:(。 这些叉子将永远存在 - 说实话 - 我不知道为什么。 我使用这个脚本几个月。 没有改变任何东西(虽然许多事情取决于外部变量)。 每个fork都必须从网站下载页面,解析它并将结果保存到文件中。 每叉不应超过30秒。 超时设置为180秒。 那些悬挂叉是完全随机的,因此很难追踪问题。 这就是为什么我想出一个临时的,简单的解决方案 - 超时和杀死。
什么可能在我的代码中禁用(中断)你的超时方法? 我的代码中的任何地方都没有任何其他alarm()
。
其中一个分叉,悬挂1小时38分钟并返回“超时PID” - 这就是我在die()
键入的alarm()
。 所以超时工作...但它的晚期大约1小时36分钟;)。 你有什么想法?
更新
很抱歉在收盘后更新,但如果我没有指出Parallel :: ForkManager也支持run_on_start
回调,那将是我的run_on_start
。 这可用于安装“子注册”功能,该功能负责为您提供PID的time()
。
例如,
$pm->run_on_start(sub { my $pid = shift; $workers{$pid} = time(); });
结果是,与下面描述的run_on_wait
一起,P :: FM的主循环不需要做任何特殊的事情。 也就是说,它可以保持简单的$pm->start and next
,并且回调将处理其他所有事情。
原始答案
Parallel :: ForkManager的run_on_wait
处理程序和一些记账,可以强制挂起和ALRM证明的孩子终止。
该函数注册的回调可以定期运行,而$pm
等待终止子进程。
use strict; use warnings;
use Parallel::ForkManager;
use constant PATIENCE => 90; # seconds
our %workers;
sub dismiss_hung_workers {
while (my ($pid, $started_at) = each %workers) {
next unless time() - $started_at > PATIENCE;
kill TERM => $pid;
delete $workers{$pid};
}
}
...
sub main {
my $pm = Parallel::ForkManager->new(10);
$pm->run_on_wait(\&dismiss_hung_workers, 1); # 1 second between callback invocations
for (1 .. 1000) {
if (my $pid = $pm->start) {
$workers{$pid} = time();
next;
}
# Here we are child. Do some work.
# (Maybe install a $SIG{TERM} handler for graceful shutdown!)
...
$pm->finish;
}
$pm->wait_all_children;
}
(正如其他人所说,最好让孩子通过alarm()
来调节自己alarm()
,但这对你来说似乎是间歇性的。你也可以采取浪费,粗暴的行为,例如让每个孩子自己fork() or exec('bash', '-c', 'sleep 90; kill -TERM $PPID')
。)
你只需要一行:
use Parallel::ForkManager;
my $pm = Parallel::ForkManager->new( 10 );
for ( 1 .. 1000 ) {
$pm->start and next;
alarm 90; # <---
# some job for fork
$pm->finish;
}
$pm->wait_all_children();
您不需要设置信号处理程序,因为您的意思是让进程死亡。
它即使你工作exec
的孩子。 它不适用于Windows,但首先在Windows上使用fork
是有问题的。
在你的子进程中(即在$pm->start and next
以及循环结束之间)做你所链接的答案。你需要做什么才能让它与Parallel :: ForkManager进行交互,其他而不是确保你不小心杀死父母:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.