为什么我的代码使用Parallel :: ForkManager生成僵尸?

时间:2016-08-05 21:29:57

标签: perl fork zombie-process

我写的一段代码使用Parallel::ForkManager,我注意到它在脚本运行时会创建许多僵尸。我想知道在wait_all_children时我是否遗漏了一些东西。

my $fork_manager = new Parallel::ForkManager->($ENV{CPUS})

for(my $i = 0; $i < scalar @plates; $i++){
    my $offset = get_full_plate_offsets(@{$plates[$i]});
    make_path(File::Spec->catfile($tmp_dir, $i));
    foreach my $cell (keys %{$offset}){
        my($x, $y) = @{$offset->{$cell}};
        $fork_manager->start("$cell @ $x, $y") and next;
        my $out_file = File::Spec->catfile($tmp_dir, $i, "$cell.jpg");
        my $out_text = File::Spec->catfile($tmp_dir, $i, "$cell.txt");
        split_file($input_jpg, [$x, $y], $out_file);
        my $result = do_something($out_file);
        open(my $FH, '>', $out_text);
        print $FH "$result\n";
        $fork_manager->finish;
    }
    $fork_manager->wait_all_children;
}

也是一个澄清问题。僵尸总是坏的吗?

起初我的印象是,僵尸流程只是尚未被其父母恢复的流程。现在,我想知道我的代码是不是在等待孩子们。

1 个答案:

答案 0 :(得分:4)

P :: FM仅在调用start并且最大子项数正在运行且调用wait_childrenwait_all_children时收到。在那之前退出的孩子们变成了僵尸。

你永远不会有比指定更多的孩子(包括僵尸),所以僵尸的临时存在并不是一件好事 [1] 。唯一的问题是run_on_finish处理程序只会在收到子进程时执行,因此这表示它没有被尽快调用。

我相信您可以使用以下方法更快地收获孩子:

$SIG{CHLD} = sub { $pm->wait_children };
  1. 有关一般答案,请参阅Is a persistent zombie process sign of a bug?