Perl,如何使用信号处理程序打破循环sub

问题描述:

假设我有一个打开的文件句柄,或者任何我必须在退出脚本之前解决的问题。 我也有一个长循环,如果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

清理代码:

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