How to tell when an IPC::Run job has finished

元气小坏坏 提交于 2019-12-06 07:26:25

I have not been able to find a clean way to do either, only other ways.

Information about whether children are running can be obtained by result related methods, and by pumpable (what is already used in the question).

The result method "Throws an exception if an out-of-range child number is passed". This happens if we query when no kids exited yet. So, with a single child process

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

Better yet, results method returns a list of child exit values while it also "Throws an exception if the harness is not in a finished state". So it can be used the same way but with more kids it can also be used to keep track of how many exited/are left.

As used in the question, pumpable can also inform whether any processes are running

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

It relates to I/O channels or processes, but if anything is running it must return true, otherwise false.

The question of children PID is a bit vexing for me, since it is information that one may need to know. While it is right in the object, $handle->{KIDS}[0]{PID} (for first kid), I don't see how to retrieve it in a reasonable way. I'd think that a structure this basic can't change, so it would tempt me to actually use it, with checks. Then I'd also be content with whatever I may get, having deserved it.

Once PID is retrieved one can check up on the process with kill 0, $pid. Note that this returns true (1) until the process has been reaped (even when it exited but is a zombie).

Here is a workaround to get the child PID. Then you can wait for the child or set up a SIGCHLD handler. For example:

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";
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!