Windows 中的 Perl kill(0, $pid) 总是返回 1 [英] Perl kill(0, $pid) in Windows always returning 1
问题描述
我正在尝试制作一个 Perl 脚本,该脚本将在 Windows 中运行一组其他程序.我需要能够捕获进程的 stdout、stderr 和退出代码,并且我需要能够查看进程是否超过了分配的执行时间.现在,我的代码的相关部分如下所示:
I'm trying to make a Perl script that will run a set of other programs in Windows. I need to be able to capture the stdout, stderr, and exit code of the process, and I need to be able to see if a process exceeds it's allotted execution time. Right now, the pertinent part of my code looks like:
...
$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.这使得我的循环在允许的全部时间内运行.
Everything is working correctly if $time = -1
(no timeout is needed), but the system thinks that kill 0, $pid
is always 1. This makes my loop run for the entirety of the time allowed.
一些额外的细节只是为了清楚起见:
Some extra details just for clarity:
- 这是在 Windows 上运行的.
- 我知道我的进程会终止,因为我得到了所有预期的输出.
- Perl 版本:这是为 MSWin32-x86-multi-thread 构建的 perl,v5.10.1(有 2 个已注册的补丁,请参阅 perl -V 了解更多详细信息)版权所有 1987-2009,Larry Wall二进制版本 1007 [291969] 由 ActiveState http://www.ActiveState.com 提供建于 2010 年 1 月 26 日 23:15:11
- 感谢您的帮助:D
- This is being run on Windows.
- I know my process does terminate because I have get all the expected output.
- Perl version: This is perl, v5.10.1 built for MSWin32-x86-multi-thread (with 2 registered patches, see perl -V for more detail) Copyright 1987-2009, Larry Wall Binary build 1007 [291969] provided by ActiveState http://www.ActiveState.com Built Jan 26 2010 23:15:11
- I appreciate your help :D
对于未来可能遇到类似问题的人我得到了代码,这是修改后的代码部分:
For that future person who may have a similar issue I got the code to work, here is the modified code sections:
$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
:
Instead of kill 0
, use waitpid $pid, WNOHANG
:
use POSIX qw( WHOHANG );
if (waitpid($pid, WNOHANG) > 0) {
# Process has ended. $? is set.
...
}
这篇关于Windows 中的 Perl kill(0, $pid) 总是返回 1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!