我正在测试我的源代码,其中子进程调用其他几个程序(其中一些是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 ++程序一旦启动就无法被杀死?
答案 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.