4

为什么这个简单的脚本:

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

(好吧,我承认它是perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-threadWindows 7 amd64 -vs-perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi在 Debian 6.0.4 盒子上的草莓,但我怀疑它对这些基本的东西很重要。编辑:我刚刚用 ActiveState perl 5.12 在类似的盒子上检查过它,它是一样的,所以显然这个问题并不局限于草莓。)

我知道perlport说得很清楚,

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

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

那么应该做些什么不同的事情呢?

4

3 回答 3

4

您可以使用sigtrap编译指示:

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

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

于 2012-06-06T10:47:57.770 回答
1

在 DOS 应用程序中遵守 unix 行规是一种奢侈,而不是一种权利。

它确实服从Ctrl+Break,这是 Ctrl+C 的 windows 等效项

编辑更改为 Ctrl+Break - 这是我使用 mac 键盘得到的。

为了测试中断处理的目的,您应该在您的工作子程序中使用以下循环,否则它会等到整个睡眠完成后再触发处理程序:

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

这样,它更容易检测到按键 - 在睡眠过程中不会检测到中断处理。

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

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

于 2012-06-06T10:34:59.357 回答
1

在添加了更多之后print,我发现实际上,代码确实可以工作,只是它在sleep.

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

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

于 2012-06-06T11:20:54.620 回答