如何判断IPC :: Run作业何时完成

问题描述 投票:2回答:2

是否有一种简单,可靠的方式来判断IPC::Run任务何时完成,即任何子进程已退出?

文档对此非常沉默。

似乎在pumpable上循环工作,虽然它没有真正记录为正确的做事方式:

use strict;
use warnings;
use IPC::Run;
use 5.12.0;

my $handle = IPC::Run::start(['sleep', '10']);

while ($handle->pumpable)
{
    sleep(0.5);
    # do other stuff in the event loop
    # so we don't want to block on finish
}

$handle->finish;

print("exited with '" . $handle->result . "'");

有更好的选择吗? finish阻止,但是当你等待proc完成时,你不能在事件循环中做其他工作。

我很惊讶没有一个简单的

$handle->running

要么

$handle->finished

我错过了一些明显的东西吗

同样地,似乎没有记录的方法来获得孩子的pid(ren)。

perl perl-ipc-run
2个回答
1
投票

我无法找到一种干净的方式,只有其他方式。

有关儿童是否跑步的信息可以通过result相关方法和pumpable(问题中已经使用的内容)获得。

result方法“如果超出范围的子号码,则抛出异常”。如果我们在没有孩子退出时查询,就会发生这种情况。因此,使用单个子进程

sub only_kid_finished { eval { $_[0]->result }; return $@ ? 0 : 1 }

更好的是,results方法返回一个子退出值列表,同时它还“如果线束未处于完成状态则引发异常”。因此它可以以相同的方式使用,但是对于更多的孩子,它也可以用于跟踪退出/剩余的数量。

正如问题中所使用的那样,pumpable还可以通知任何进程是否正在运行

sub any_kids_left { return $_[0]->pumpable }

它与I / O通道或进程有关,但如果有任何正在运行它必须返回true,否则返回false。

儿童PID的问题对我来说有点令人烦恼,因为这是人们可能需要知道的信息。虽然它是对象,$handle->{KIDS}[0]{PID}(第一个孩子),我不知道如何以合理的方式检索它。我认为这个基本的结构不能改变,所以它会诱使我实际使用它,并带有支票。然后我也会满足于我可能获得的任何东西,当之无愧。

一旦检索到PID,就可以使用kill 0, $pid检查进程。请注意,这将返回true(1),直到获得该进程(即使它已退出但是是僵尸)。


1
投票

这是获取子PID的解决方法。然后您可以等待孩子或设置SIGCHLD处理程序。例如:

use feature qw(say);
use strict;
use warnings;

use IPC::Run qw( start );
use Proc::ProcessTable;

my $h = start ['sleep', '5'];

my $pt = Proc::ProcessTable->new();
my $kid;
for my $p (@{ $pt->table } ){
    if ( $p->ppid == $$ ) {
        if ( $p->cmndline =~ m{/bin/sleep} ) {
            $kid = $p->pid;
        }
    }
}

if ( defined $kid ) {
    say "Waiting for child with PID '$kid' to finish..";
    waitpid $kid, 0;
    say "Done.";
}
else {
    die "Could not find PID of child process\n";
}
© www.soinside.com 2019 - 2024. All rights reserved.