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

时间:2012-06-06 10:06:38

标签: windows perl signals

为什么这个简单的脚本:

#! 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";)做同样的事情,窗口会关闭,但无论如何都不会执行干净的退出)

(好吧,我承认在Debian 6.0.4的Windows 7 amd64 -vs- perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread上是草莓perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi,但我怀疑这些基本内容是否重要。编辑:我刚用类似的方法在ActiveState perl 5.12上检查它,它是相同的,所以显然这个问题并不是草莓所隔离的。)

我知道perlport说得很清楚,

  

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

但必须有办法...(另外,我想了解。)

那么应该做些什么呢?

3 个答案:

答案 0 :(得分:4)

您可以使用sigtrap pragma:

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

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

答案 1 :(得分:1)

在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窗口的关闭时似乎没有传递该事件< / p>

答案 2 :(得分:1)

在添加了更多print之后,我发现实际上代码 可以正常工作,除了它在sleep期间不会中断。

因此,只需将sleep 60更改为更“现实”sleep 1 foreach (1..10);,就会带来更多可接受的行为。

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