假设我有一个打开的文件句柄,或者在退出脚本之前我必须修复的任何内容。 我也有一个很长的循环,如果processus收到一个sigint,我想打破循环。最干净的方法是什么?
以下是问题的说明;
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")
答案 0 :(得分:4)
绝对应该运行的清理代码可以放入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
。
因此,当您使用SIGINT终止它时,此代码将不会打印END
:
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
。