Windows中的Perl kill(0,$ pid)总是返回1

时间:2012-11-09 21:51:01

标签: windows perl process

我正在尝试创建一个在Windows中运行一组其他程序的Perl脚本。我需要能够捕获进程的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-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

对于未来可能有类似问题的人 我得到了代码,这里是修改后的代码部分:

        $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);

1 个答案:

答案 0 :(得分:4)

而不是kill 0,请使用waitpid $pid, WNOHANG

use POSIX qw( WHOHANG );

if (waitpid($pid, WNOHANG) > 0) {
   # Process has ended. $? is set.
   ...
}