2010-10-30 20 views
4

我有这个简单的Perl守护进程:在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信号就会中断睡眠。

这是怎么回事?

回答

8

从您的程序将处理传入信号的意义上说,睡眠正在中断,但是回路将继续(回到睡眠状态),直到收到TERM信号。这被记录的行为为sleep()功能:如果该进程接收到一个信号,如“SIGALRM”

可能会中断。

注意,如果你需要睡30秒,即使信号中断,你能确定的秒数睡觉,然后再睡觉,其余:

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

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

+3

你不检查,看看你的第二个'睡眠'也被打断了。为了正确处理它,你需要一个循环,而不仅仅是一个'if'。 – cjm 2010-10-30 22:14:41

+0

呃,编辑的答案是一个无限循环。 :( – mark4o 2010-10-31 05:58:15

+0

@ mark4o:无限,直到信号中断它,是的,这通常是守护进程。(为了清楚起见,我删除了'$ continue'变量,因为它与睡眠行为的核心问题无关显然有人可能想让实际的代码更加复杂,例如在cjm提到的第二次中断时再次睡觉。) – Ether 2010-10-31 17:00:40