2016-08-05 104 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