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
。
@derpness感谢您的建议编辑。每个循环设置处理程序确实是不需要的,但我想将其放在块中以用于范围目的。更好的解决方案应该是'{my $ run = 1;使用sigtrap ...; while($ run){...}}'。无论如何,这与代码的主要目的是非常接近的,所以你的建议没有被合并。 – amon
sigtrap和范围的陈述是不正确的[从代码的角度来看,可能(?)来自人类的理解]。添加: BEGIN {$ sigtrap :: Verbose = 1; }打印“正在运行\ n”; 到“my $ ...”之前,表明信号处理程序是在编译时安装的 - 由于使用语句。在这两个例子中,它都会导致全球范围内的信号处理。 – Mathew