2011-09-15 142 views
3

我在perl中使用了Thread::Pool模塊來並行化一些perl代碼。這個過程需要一段時間,偶爾我會用SIGINT從命令行中終止它。正如我所料,這樣做會導致程序突然結束。這留下了一些凌亂的臨時文件,所以我想安裝一個信號處理程序。我這樣做:螺紋perl和信號處理程序

sub INT_Handler{ 
    #clean up code 
    exit(1); 
} 
$SIG{'INT'} = 'INT_handler'; 

在創建線程池和啓動線程之前。現在,當我發送正在運行的SIGINT,worker threads,但池會立即啓動另一組工作人員處理下一組作業並繼續運行。爲什麼在信號處理程序中退出的調用不會退出主線程?我需要什麼來阻止該進程運行?

編輯響應暴民的評論

**進一步編輯**

這裏是我寫了一個例子。

use Thread::Pool; 

sub INT_handler{ 
    print "Handler\n"; 
    exit(1); 
} 

$SIG{'INT'}='INT_handler'; 

sub f{ 
    print "Started a thread " . rand(10000) . "\n"; 
    sleep(10); 
} 

my $pool; 
my $submit = \&f; 

if (0){ 
$pool = Thread::Pool->new({do=>'f', workers=>5}); 
    $submit = sub{ $pool->job; } 
} 

for (my $i = 0; $i < 100; $i++){ $submit->(); } 

$pool->shutdown if defined $pool; 

0,我看到預期的結果

h:57 Sep 15 16:15:19> perl tp.pl 
Started a thread 3224.83224635111 
Handler 

1,出現這種情況

h:57 Sep 15 16:14:56> perl tp.pl 
Started a thread 5034.63673711853 
Started a thread 9300.99967009486 
Started a thread 1394.45532885478 
Started a thread 3356.0428193687 
Started a thread 1424.4741558014 

等和處理程序沒有得到進入和進程繼續運行。我不得不用SIGINT以外的信號殺死進程。如果沒有處理程序,這兩種情況都會在通過SIGINT時退出。

+1

這與[文檔]爭論(http://search.cpan.org/perldoc?threads#BUGS_AND_LIMITATIONS):「腳本的主線程(線程ID = 0)捕獲*信號。 「你能隔離併發布一些代碼,這些代碼在工作線程中似乎被捕獲到了嗎? – mob

+0

@mob好的,所以我必須誤認爲信號被工作人員抓住了。我認爲是這樣,因爲我明確地在信號處理程序中調用exit。然而,我觀察到的是正在運行的工作者線程以及正在啓動的一組新工人。 –

回答

4

這更像是一個暗示,而不是一個明確的答案,但是看起來你的主線程永遠不會處於運行信號處理程序的「安全」狀態。它的工作,當您啓用Perl的不安全的信號:

PERL_SIGNALS=unsafe perl tp.pl

對安全和不安全的信號的更多信息,請參見perlipc - 也許它會導致你在正確的方向與安全信號來實現它(因爲它可能應該)。


(由暴民更新)大廈米哈爾原有的洞察力,此解決辦法 Perl::Unsafe::Signals也得到了處理工作,因爲你所期望

use Perl::Unsafe::Signals; 
... 
UNSAFE_SIGNALS { 
    $pool->shutdown if defined $pool; 
}; 

所以很明顯它是一些有關Perl的安全信號機制,這是在通往處理程序的路上干擾信號。我想知道是否可以通過在Thread::Pool::shutdown之內放入UNSAFE_SIGNALS { ... }塊來解決這個問題。無論哪種方式,我會file a bug report關於此。

+0

我嘗試在我的示例頂部添加了'$ ENV {PERL_SIGNALS} =「unsafe」;'但我仍然遇到同樣的問題。但是,如果我在運行腳本之前設置了環境變量,它確實有效。這是爲什麼? –

+1

該變量可能僅在perl開始執行腳本時才被評估,因此在腳本中設置它爲時已晚。 –

+1

我發現了一個線程[here](http://groups.google.com/group/perl.perl5.porters/browse_thread/thread/7cd25dcb2661ed67/3eeb441f1ce3e959?lnk=raot),有人抱怨「PERL_SIGNALS」的內部設置停止在5.14時工作,直到那時他纔開心地使用它。我正在使用5.8.8!儘管如此,我可能會安裝'Perl :: Unsafe :: Signals'。 –