2016-11-17 44 views
2

是否有简单可靠的方法来判断IPC::Run任务何时完成,即任何子进程已退出?如何判断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。

+0

'$ handle-> finish'块,比如'wait'。如果你想在等待之前检查,调用'result' _before_ child显然抛出一个异常,所以你可以通过检查异常--eval {$ res = $ handle-> result}来使用它,或者打印“Still running \ n“个;'。这是一个kludge(应该检查'$ @'而不是'或' - 它),但这样做吗?还有一些其他版本的结果。还有一个'信号',我试图发送一个'0',但我什么都没有回来。文档中似乎暗示pid不能直接使用。 – zdim

+0

呃。是的,可以尝试调用'result'并捕获异常。丑陋:(我应该明确表示我正在寻找一种非阻塞方式,否则我只是使用'IPC :: Run :: run'。谢谢。 –

+0

对,我确实得到了,但提到了以防万一,这是丑陋的,但我现在看不到更清洁的方式(我没有太多使用这个模块,我会看起来更多,因为我一直想更好地检查它。) – zdim

回答

1

我还没有找到一种干净的方式来做,只有其他方式。

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

result方法“如果超出范围的子编号通过将引发异常”。如果我们查询何时没有孩子退出,就会发生这种情况。所以,用一个单一的子进程

sub only_kid_finished { eval { $_[0]->result }; return [email protected] ? 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"; 
} 
相关问题