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

时间:2014-11-08 19:01:44

标签: multithreading perl loops parallel-processing fork

我想让Parallel :: ForkManager使用回调来从子进程中获取某些内容,然后重新启动它。那可能吗?以下内容来自Parallel :: ForkManager docs:

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->完成时,回调确认“孩子”是“不在游泳池外”。我怎样才能让回调发射并立即将孩子放回池中,以便它永远运行?

1 个答案:

答案 0 :(得分:1)

我认为你误解了正在发生的事情。在幕后,Parallel :: ForkManager正在做的是调用fork()。此时存在两个过程,只有一个差异 - 不同的PID。

你的子进程会运行并运行一些东西,然后退出,生成一个退出状态,然后你的父进程就会收到。

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

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

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

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

您是否考虑过将线程作为替代方案?线程适用于共享内存操作传递密钥子进程是它擅长的东西。