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

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

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

4

2 回答 2

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";
}
于 2016-11-17T10:32:30.043 回答
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),直到进程被收割(即使它退出但它是僵尸)。

于 2016-11-17T19:00:01.263 回答