我试图做一个Perl脚本,将在Windows中运行一组其他程序。 我需要能够捕获进程的stdout,stderr和退出代码,并且我需要能够看到一个进程是否超出了分配的执行时间。 现在,我的代码的相关部分如下所示:
... $pid = open3($wtr, $stdout, $stderr, $command); if($time < 0){ waitpid($pid, 0); $return = $? >> 8; $death_sig = $? & 127; $core_dump = $? & 128; } else{ # Do timeout stuff, currently not working as planned print "pid: $pid\n"; my $elapsed = 0; #THIS LOOP ONLY TERMINATES WHEN $time > $elapsed ...? while(kill 0, $pid and $time > $elapsed){ Time::HiRes::usleep(1000); # sleep for milliseconds $elapsed += 1; $return = $? >> 8; $death_sig = $? & 127; $core_dump = $? & 128; } if($elapsed >= $time){ $status = "FAIL"; print $log "TIME LIMIT EXCEEDED\n"; } } #these lines are needed to grab the stdout and stderr in arrays so # I may reuse them in multiple logs if(fileno $stdout){ @stdout = <$stdout>; } if(fileno $stderr){ @stderr = <$stderr>; } ...
如果$time = -1
(不需要超时),一切都正常工作,但系统认为kill 0, $pid
始终是1.这使得我的循环运行的整个时间允许。
一些额外的细节只是为了清楚:
对于可能有类似问题的未来人员,我得到了代码工作,这里是修改的代码部分:
$pid = open3($wtr, $stdout, $stderr, $command); close($wtr); if($time < 0){ waitpid($pid, 0); } else{ print "pid: $pid\n"; my $elapsed = 0; while(waitpid($pid, WNOHANG) <= 0 and $time > $elapsed){ Time::HiRes::usleep(1000); # sleep for milliseconds $elapsed += 1; } if($elapsed >= $time){ $status = "FAIL"; print $log "TIME LIMIT EXCEEDED\n"; } } $return = $? >> 8; $death_sig = $? & 127; $core_dump = $? & 128; if(fileno $stdout){ @stdout = <$stdout>; } if(fileno $stderr){ @stderr = <$stderr>; } close($stdout); close($stderr);
而不是kill 0
,使用waitpid $pid, WNOHANG
:
use POSIX qw( WHOHANG ); if (waitpid($pid, WNOHANG) > 0) { # Process has ended. $? is set. ... }