我正在尝试制作一个 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。这使得我的循环在允许的整个时间内运行。
为了清楚起见,一些额外的细节:
- 这是在 Windows 上运行的。
- 我知道我的进程确实终止了,因为我已经得到了所有预期的输出。
- Perl 版本:这是为 MSWin32-x86-多线程构建的 perl,v5.10.1
(有 2 个注册补丁,请参阅 perl -V 了解更多详细信息)版权所有 1987-2009,Larry Wall
ActiveState 提供的二进制版本 1007 [291969]http://www.ActiveState.com http://www.ActiveState.com建成于 2010 年 1 月 26 日 23:15:11
- 我感谢你的帮助:D
对于未来可能有类似问题的人我让代码可以工作,这里是修改后的代码部分:
$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);