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

Why is my code using Parallel::ForkManager producing zombies?

我正在编写的一段代码使用 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;
}

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

起初我的印象是僵尸进程只是尚未被 parent 恢复的进程。现在我想知道我的代码是否根本没有在等待 children。

P::FM只在调用start时收获,最大children数为运行,当wait_childrenwait_all_children时被称为。 Children 出口变成僵尸直到那时。

您的 children(包括僵尸)永远不会超过指定数量,因此僵尸的临时存在并不是一件坏事[1]。唯一的问题是 run_on_finish 处理程序只会在 child 进程被回收时执行,因此这表明它不会被尽快调用。

我相信你可以通过以下方式来更快地收获child仁:

$SIG{CHLD} = sub { $pm->wait_children };

  1. 请参阅 Is a persistent zombie process sign of a bug? 以获得一般答案。