2016-08-05 68 views
2

我写的一段代码使用Parallel::ForkManager,我注意到它正在创建许多僵尸脚本运行。我想知道如果我在wait_all_children中错过了什么。为什么我的代码使用Parallel :: ForkManager生成僵尸?

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; 
} 

另外一个澄清的问题。僵尸总是不好对吧?

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

回答

4

P ::调频收音机只调用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?
+0

你不觉得Parallel :: ForkManager已经使用了SIGCHLD处理程序吗? – mob

+0

太棒了,我担心有一个代码味道:僵尸。也许我错过了关于共享状态的细节。正如你所说的,可能是孩子们在wait_all_children到达之前完成的。关于on_finish有趣的一点,当我看到自己使用更多的ForkManager时,我会记住这一点。 – cwisch

+0

@mob,它不会(除非在非常特定的情况下,在非常局部的区域)。如果是这样,僵尸会在我加入的线路出现后立即收获。 – ikegami