2010-10-30 41 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