忽略超时的Perl kill进程

时间:2017-05-11 21:09:22

标签: perl process

我正在测试我的源代码,其中子进程调用其他几个程序(其中一些是C ++)。

#Other variables and functions

my $MAX_TIME = 10;#testing 10 minutes
my $timeRemaining = $MAX_TIME * 60;
my $pid = fork();
if ( $pid == 0 ) {
  #child process
  my $nowTime = localtime;
  print "Run started at $nowTime\n";

  #This run() calls a for loop in perl, in each iteration there are several C++ programs
  run();

  setpgrp(0,0);
}
elsif ($pid > 0){
  my $nowTime = localtime;
  eval{
    local $SIG{ALRM} = sub {
      kill -9, $pid;
      print "Run completed at $nowTime\nJob time out for $MAX_TIME minutes\n";
      log();
      die "TIMEOUT!\n";
    };
    alarm $timeRemaining;
    waitpid($pid, 0);
  };
  print "Run completed at $nowTime with no timeout\n";
}

当我检查打印输出时,我注意到在10分钟后,"运行在$ nowTime完成,没有超时\ n"部分被打印出来,子进程仍在执行。父进程中的die "TIMEOUT!\n";部分未执行。 是不是因为Perl程序调用的C ++程序一旦启动就无法被杀死?

1 个答案:

答案 0 :(得分:3)

首先,kill失败,因为$pid不是一个进程组。

run();
setpgrp(0,0);

应该是

setpgrp(0,0);
run();

其次,你看到

的原因
Run completed at $nowTime with no timeout

即使超时也要执行

print "Run completed at $nowTime with no timeout\n"; 

是否超时。

第三,当收获孩子时,你不要禁用alarm。添加

alarm(0);

第四,你期望$nowTime包含当前时间而不是这样。

最后,即使你杀了孩子,你仍然需要收获你的孩子。 (好吧,如果父母立即退出,可以跳过这个。)

修正:

use strict;
use warnings;

use POSIX qw( strftime );

sub current_time { strftime("%Y-%m-%d %H:%M:%S", localtime) }

sub run {
  print("a\n");
  system('perl', '-e', 'sleep 3;');
  print("b\n");
  system('perl', '-e', 'sleep 3;');
  print("c\n");
}

my $MAX_TIME = 5;
my $pid = fork();
die($!) if !defined($pid);
if ($pid) {
  if (eval{
    local $SIG{ALRM} = sub {
      kill KILL => -$pid;
      die "TIMEOUT!\n";
    };
    alarm($MAX_TIME);
    waitpid($pid, 0);
    alarm(0);
    return 1;
  }) {
    print "[".current_time()."] Run completed.\n";
  } else {
    die($@) if $@ ne "TIMEOUT!\n";
    print "[".current_time()."] Run timed out.\n";
    waitpid($pid, 0);
    print "[".current_time()."] Child reaped.\n";
  }
} else {
  print "[".current_time()."] Run started.\n";
  setpgrp(0,0);
  run();
}

输出:

[2017-05-11 14:58:06] Run started.
a
b
[2017-05-11 14:58:11] Run timed out.
[2017-05-11 14:58:11] Child reaped.