在Windows上捕获SIGINT(和其他信号)

为何这个简单的脚本:

#! perl -w use strict; use warnings; $| = 1; my $LOCKFILE = "$0.lock"; sub mklock { open my $lf, ">", $LOCKFILE; print $lf $$; close $lf; } sub rmlock { unlink $LOCKFILE; } sub clean_exit { rmlock; exit 0; } sub work { print "working..."; sleep 10; # although `sleep 1 foreach (1..10);` # *does* interrupt---between `sleep`s--see my answer print "done.\n" } $SIG{INT} = "clean_exit"; mklock; work; rmlock; 

在Debian上运行,但不在Windows上运行?

  • 在Windows上,当这个脚本正在工作时, Ctrl + C被忽略
  • 在Debian上,干净的退出按预期执行
  • $SIG{INT} = \&clean_exit; ,行为似乎是一样的
  • (如果我对SIGHUP$SIG{HUP} = "clean_exit"; )做同样的操作,窗口closures,但干净的退出不会执行)

(好吧,我承认,它是perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread Windows 7上的perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread的草莓perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread amd64 -vs- perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi在Debian 6.0.4框中,但我怀疑这是基本的东西。 编辑:我刚刚检查过与ActiveState的perl 5.12类似的盒子,这是相同的,显然这个问题不是孤立的草莓。)

我知道perlport说清楚,

不要指望任何信号或%SIG。

但一定有办法…(另外,我想明白)

那么应该做些什么不同?

您可以使用sigtrap注:

 use sigtrap 'handler', \&cleanup, 'normal-signals'; 

当信号被捕获时,这将调用方法cleanup ,并将信号标识作为参数传递。

在添加了更多的print之后,我发现实际上,代码确实起作用,除了在sleep期间不中断。

所以只是改变sleep 60更“现实”的sleep 1 foreach (1..10); 带来更多可接受的行为。

当然,它在Windows上的工作方式与在* nix上的工作方式不同。

遵循DOS应用程序中的unix行纪律是一种奢侈,而不是一种权利。

它遵守Ctrl+Break ,这是Ctrl + C的等效窗口

编辑改变为Ctrl + Break – 这是我得到使用Mac键盘。

为了测试中断处理的目的,你应该在你的工作副本中使用下面的循环,否则在触发处理程序之前一直等到整个睡眠完成。

 sub work { print "working..."; my $i = 0; while ($i < 10) { sleep(1); $i--; } say "done." } 

这样就更容易检测到按键 – 正在进行睡眠时中断处理没有被检测到。

让我感到困惑 – INT处理程序正在工作!

编辑 Perl的原始源代码声称它应该支持HUP作为关闭窗口事件,但是当我点击一个CMD窗口关闭时,事件似乎没有被传递