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

时间:2013-08-28 17:38:23

标签: perl while-loop signals

假设我有一个打开的文件句柄,或者在退出脚本之前我必须修复的任何内容。 我也有一个很长的循环,如果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")

1 个答案:

答案 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