【问题标题】:Why is my code using Parallel::ForkManager producing zombies?为什么我的代码使用 Parallel::ForkManager 会产生僵尸?
【发布时间】:2016-08-05 21:29:57
【问题描述】:

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

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

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

【问题讨论】:

    标签: perl fork zombie-process


    【解决方案1】:

    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? 以获得一般性答案。

    【讨论】:

    • 你不认为 Parallel::ForkManager 已经使用了 SIGCHLD 处理程序吗?
    • 太好了,我担心有代码气味:僵尸。也许我错过了有关共享状态的细节。正如您所说,可能是孩子们在达到 wait_all_children 之前完成。关于 on_finish 有趣的一点,当我看到自己使用更多的 ForkManager 时,我会记住这一点。
    • @mob,它没有(除非在非常局部的区域中非常特殊的情况下)。如果是这样,僵尸将在孩子退出时立即收割,就像我添加的行一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 2013-04-11
    相关资源
    最近更新 更多