在perl中收到任何信号时,睡眠会中断吗?

时间:2010-10-30 21:11:36

标签: linux perl signals daemon

我有这个简单的perl守护进程:

#!/usr/bin/perl

use strict;
use warnings;
use Proc::Daemon;

Proc::Daemon::Init;

my $continue = 1;

$SIG{TERM} = sub { $continue = 0 };
$SIG{USR1} = sub { do_process(1) };

# basic daemon                                                                                    

boxesd_log("started boxesd");

while ($continue) {
    do_process(0);
    sleep(30);
}

boxesd_log("finished boxesd");

exit(0);

# required subroutines                                                                            

sub do_process {
    my ($notified) = @_;
    boxesd_log("doing it $notified");
}

但有些事情是行不通的。

当守护程序启动时,它会每隔30秒记录一次,而不会按预期通知:

Sat Oct 30 21:05:47 2010 doing it 0
Sat Oct 30 21:06:17 2010 doing it 0
Sat Oct 30 21:06:47 2010 doing it 0

当我使用USR1向流程发送kill -USR1 xxxxx信号时出现问题。输出不是我所期望的:

Sat Oct 30 21:08:25 2010 doing it 1
Sat Oct 30 21:08:25 2010 doing it 0

我得到两个连续的条目,一个来自信号处理子程序,另一个来自永远运行的循环。每当收到USR1信号时,似乎睡眠就会中断。

发生了什么事?

1 个答案:

答案 0 :(得分:8)

睡眠正在被中断,因为您的程序将处理输入信号,但循环将继续(返回睡眠状态),直到收到TERM信号。这是sleep()函数记录的行为:

  

如果进程收到“SIGALRM”等信号,可能会中断。

请注意,如果您需要睡30秒,即使被信号中断,您也可以确定睡眠的秒数,然后再次睡眠:

while (1)
{
    my $actual = sleep(30);
    sleep(30 - $actual) if $actual < 30;
}

PS。您可以在perldoc perlipc以及W. Richard Stevens的几乎所有unix编程手册中阅读有关信号处理的更多信息。 :)