2013-08-28 118 views
2

假設我有一個打開的文件句柄,或者任何我必須在退出腳本之前解決的問題。 我也有一個長循環,如果processus收到一個sigint,我想打破循環。什麼是最乾淨的方式來做到這一點?Perl,如何使用信號處理程序打破循環sub

下面是該問題的說明;

use sigtrap 'handler' => \&sigint_handler, 'INT'; 

sub sigint_handler { 
    print("\nI see you are trying to escape this evil infinite loop, 
but there is nothing that I can do to help you :(\n"); 
} 

my $the_developper_is_unable_to_end_this_mess = 1; 

open(my $handle, "< some.important.file"); 

while($the_developper_is_unable_to_end_this_mess) { 
    print("And the evil loop rolls again and again...\n"); 
    sleep(3); 
} 

close($handle); 

print("everything went better than expected\n") 
應該絕對運行可以被放入一個 END

回答

4

清理代碼:

END { 
    print "This is run before the program exits\n"; 
} 
print "This is some normal code\n"; 

輸出:

This is some normal code 
This is run before the program exits 

然而,END塊不是當該處理從終止運行一個信號,除非你實現你自己的信號處理程序 - 並且它所做的只是調用exit

所以這個代碼將無法打印END當你與一個SIGINT終止它:

END { print "END\n" } 
sleep 4; 

但是這一次將:

END { print "END\n" } 
local $SIG{INT} = sub { exit 1 }; 
sleep 4; 

這些處理程序動態範圍的,所以你可以把一個進入外部沒有生效的環路中:

my $run = 1; 
while ($run) { 
    local $SIG{INT} = sub { $run = 0 }; 
    print "zzz\n"; 
    sleep 3; 
} 
print "done!\n"; 

當然你可以Ñ還使用sigtrap

my $run = 1; 
while ($run) { 
    use sigtrap handler => sub { $run = 0 }, 'INT'; 
    print "zzz\n"; 
    sleep 3; 
} 
print "done!\n"; 

PS:當它們落入超出範圍/文件句柄自動關閉上過程退出。如果句柄正在從文件中讀取,則根據句柄不能有任何緩衝問題或其他進程,因此在這種情況下您可以放心地忘記close $fh

+0

@derpness感謝您的建議編輯。每個循環設置處理程序確實是不需要的,但我想將其放在塊中以用於範圍目的。更好的解決方案應該是'{my $ run = 1;使用sigtrap ...; while($ run){...}}'。無論如何,這與代碼的主要目的是非常接近的,所以你的建議沒有被合併。 – amon

+1

sigtrap和範圍的陳述是不正確的[從代碼的角度來看,可能(?)來自人類的理解]。添加: BEGIN {$ sigtrap :: Verbose = 1; }打印「正在運行\ n」; 到「my $ ...」之前,表明信號處理程序是在編譯時安裝的 - 由於使用語句。在這兩個例子中,它都會導致全球範圍內的信號處理。 – Mathew