如何在完成时使用 Parallel::ForkManager 重新启动子进程

Posted

技术标签:

【中文标题】如何在完成时使用 Parallel::ForkManager 重新启动子进程【英文标题】:How to restart child process with Parallel::ForkManager on finish 【发布时间】:2014-11-08 19:01:44 【问题描述】:

我想让 Parallel::ForkManager 使用回调从子进程中取回一些东西,然后重新启动它。那可能吗?以下来自 Parallel::ForkManager 文档:

use strict;
use Parallel::ForkManager;

my $max_procs = 5;
my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara );
# hash to resolve PID's back to child specific information

my $pm =  new Parallel::ForkManager($max_procs);

# Setup a callback for when a child finishes up so we can
# get it's exit code
$pm->run_on_finish(
  sub  my ($pid, $exit_code, $ident) = @_;
    print "** $ident just got out of the pool ".
      "with PID $pid and exit code: $exit_code\n";
  
);

$pm->run_on_start(
  sub  my ($pid,$ident)=@_;
    print "** $ident started, pid: $pid\n";
  
);

$pm->run_on_wait(
  sub 
    print "** Have to wait for one children ...\n"
  ,
  0.5
);

foreach my $child ( 0 .. $#names ) 
  my $pid = $pm->start($names[$child]) and next;

  # This code is the child process
  print "This is $names[$child], Child number $child\n";
  sleep ( 2 * $child );
  print "$names[$child], Child $child is about to get out...\n";
  sleep 1;
  $pm->finish($child); # pass an exit code to finish
#####here is where I'd like each child process to restart

所以当 $pm->finish 发生时,回调确认“孩子”是“不在池中”。我怎样才能让回调触发并在孩子出来时立即将它们放回池中,以便它永远运行?

【问题讨论】:

【参考方案1】:

我认为您误解了正在发生的事情。在幕后,Parallel::ForkManager 正在调用fork()。此时存在两个进程,只有一个区别 - 不同的 PID。

您的子进程开始运行一些东西,然后退出,生成退出状态,然后您的父进程将获得该状态。

重新启动进程...好吧,您只需要再次分叉并运行您的代码。

现在,你在做什么 - 一个 foreach 循环,那个 - foreach 数组元素,fork,然后 fork 退出。

真的 - 你需要做的就是再次致电$pm -> start。但是,您如何确定哪个退出(以及子名称)更加困难 - 您的回调在父进程中运行,因此除了您的孩子的退出状态之外,数据不会被传回。您需要找出某种 IPC 来通知必要的详细信息。

虽然 - 我要指出 @names 不是哈希,所以像对待它一样对待它会有奇怪的行为:)。

您是否考虑过使用线程作为替代方案?线程适用于共享内存操作,传递键控子进程是它擅长的事情。

【讨论】:

孩子不是用$ident传回给父母的吗?我想我是通过将 foreach 更改为 while(1)、移动孩子并将 $ident 推回回调中的数组来开始工作的。 这应该可以解决问题 - Parallel::ForkManager 所做的主要事情是启动 - 并限制 - 活动运行的进程。不过要小心一点——模块文档并没有明确说明回调何时被触发——你最终可能会在你不小心的竞争条件下构建(主代码中指令之间的数组更新)。跨度>

以上是关于如何在完成时使用 Parallel::ForkManager 重新启动子进程的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 Jquery Autocomplete 和 JSP 时设置自动完成输入框的值

如何使用 ASP.NET C# 在使用 ajax 完成 Web 服务时生成警报

使用 asyncio 时,如何让所有正在运行的任务在关闭事件循环之前完成

如何在动画完成时在 imageview 中启用交互

如何在 Fire Base 中使用完成处理程序

AWS AppSync 如何在我离线时判断是不是存在未完成的突变?