由SIGCHLD终止Perl睡眠

时间:2012-08-23 10:18:42

标签: perl

#!/usr/bin/perl

use POSIX ":sys_wait_h";
$SIG{CHLD} = \&REAPER;

sub REAPER {
  my $pid;
  while (($pid = waitpid(-1, WNOHANG)) > 0) {
      print "where is here,$pid\n";
  }
}

sub child {
  print "I'm child, pid=$$.\n";
  sleep 2;
}

$lid = fork();
if ($lid == 0) {
    &child;
    exit;
} else {
    sleep 1000;
    print "I am parent, child pid : $lid\n";
}

输出:

I'm child, pid=11839.
where is here,11839
I am parent, child pid : 11839

以上是我的Perl脚本。输出是正确的,但奇怪的是它在最后一次输出后立即打印I am parent, child pid : 11839。为什么sleep 1000没有任何效果?

2 个答案:

答案 0 :(得分:8)

这是documented:“如果进程收到信号,可能会中断”。重点是允许信号处理程序运行。如果没时间醒来,就回去睡觉吧。

use Time::HiRes qw( time sleep );  # Optional.

sub unint_sleep($) {
    my $sleep_til = time + $_[0];
    for (;;) {
        my $sleep_dur = time - $sleep_til;
        last if $sleep_dur <= 0;
        sleep($sleep_dur);
    }
}

答案 1 :(得分:2)

始终 use strictuse warnings,并在定义时使用my声明您的符号。这尤其适用于您寻求帮助的情况,因为这些措施可以揭示容易被忽视的简单错误

sleep是通过使用setitimer在指定的时间间隔后请求SIGALRM,然后pause暂停进程直到获得信号来实现的。

但如果SIGCHLD首先出现,这也会唤醒这个过程。

无法设置信号掩码以防止此情况,否则SIGCHLD将无法获得服务