perl:当程序'kill'时可以调用end块

时间:2015-03-29 15:54:27

标签: perl

BEGIN {
    while (1) {
        print "hi\n";
    }
}


END {
    print "end is called\n";
}
shell中的

kill <pid>

输出:

hi
hi
hi
hi
hi
hi
hi
hi
hi
Terminated

当我通过kill或ctrl-c杀死它时,没有调用结束块。

在程序退出之前是否总会调用等效的东西

2 个答案:

答案 0 :(得分:4)

Ctrl C向您的程序发送SIGINT。你可以抓住&#39;通过在%SIG中设置适当的条目,使用信号处理程序。我会注意到 - 我不明白为什么你这样使用BEGINBEGIN是一个特殊的代码块,在编译时调用 - 在第一次机会。这意味着当您运行perl -c来验证代码时会触发它,因此设置为无限循环确实是一个坏主意。请参阅:perlmod

E.g。

#!/usr/bin/perl

use strict;
use warnings;

$SIG{'INT'} = \&handle_kill; 
my $finished = 0; 

sub handle_kill {
     print "Caught a kill signal\n";
     $finished++; 
}


while ( not $finished ) {
    print "Not finished yet\n";
    sleep 1;
}

END {
    print "end is called\n";
}

但是有一个缺点 - 有些信号你不能以这种方式陷阱。有关详细信息,请参阅perlipc

  

某些信号既不会被捕获也不会被忽略,例如KILL和STOP(但不是TSTP)信号。请注意,忽略信号会使它们消失。如果你只想暂时阻止它们而不让它们迷路,你就必须使用POSIX&#39; sigprocmask。

默认情况下,如果您发送kill,则会发送SIGTERM。所以你可能也想要覆盖这个处理程序。然而,除了使用SIGTERM优雅地退出之外,做任何其他事情通常都被认为是不好的事情 - 做某事&#39;更容易接受。捕获SIGHUP(挂断)和SIGINT时恢复。

你应该注意到Perl会发出安全信号&#39;虽然 - 所以一些系统调用不会被中断,perl会在处理信号之前等待它返回。这是因为如果您中止某些操作(例如close在您正在刷新数据的文件上可能会导致其损坏),则可能会发生错误的事情。通常这不是问题,但需要注意的事项。

答案 1 :(得分:3)

在你的代码中输入正确的信号处理程序:

$SIG{INT} = sub { die "Caught a sigint $!" };

control-c将SIGINT信号发送给脚本,该脚本由此处理程序

捕获