user2387065
user2387065

Reputation: 11

How to restart child process with Parallel::ForkManager on finish

I'd like to have Parallel::ForkManager use a callback to get something back from a child process and then also restart it. Is that possible? The following is from the Parallel::ForkManager docs:

use strict;
use Parallel::ForkManager;

my $max_procs = 5;
my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara );
# hash to resolve PID's back to child specific information

my $pm =  new Parallel::ForkManager($max_procs);

# Setup a callback for when a child finishes up so we can
# get it's exit code
$pm->run_on_finish(
  sub { my ($pid, $exit_code, $ident) = @_;
    print "** $ident just got out of the pool ".
      "with PID $pid and exit code: $exit_code\n";
  }
);

$pm->run_on_start(
  sub { my ($pid,$ident)=@_;
    print "** $ident started, pid: $pid\n";
  }
);

$pm->run_on_wait(
  sub {
    print "** Have to wait for one children ...\n"
  },
  0.5
);

foreach my $child ( 0 .. $#names ) {
  my $pid = $pm->start($names[$child]) and next;

  # This code is the child process
  print "This is $names[$child], Child number $child\n";
  sleep ( 2 * $child );
  print "$names[$child], Child $child is about to get out...\n";
  sleep 1;
  $pm->finish($child); # pass an exit code to finish
#####here is where I'd like each child process to restart
}

So when $pm->finish happens, the callback confirms the "child" is "out of the pool." How can I both get the callback to fire and immediately put the child back in the pool as they come out, so that it runs forever?

Upvotes: 0

Views: 583

Answers (1)

Sobrique
Sobrique

Reputation: 53498

I think you're misunderstanding what's happening. Under the covers, what Parallel::ForkManager is doing is calling a fork(). Two processes exist at this point, with only a single difference - different PIDs.

Your child process goes and runs some stuff, then exits, generating an exit status, which your parent then reaps.

Restarting the process... well, you just need to fork again and run your code.

Now, what you're doing - a foreach loop, that - foreach array element, forks and then the fork exits.

So really - all your need to do, is call $pm -> start again. How you figure out which one exited (and thus the child name) is more difficult though - your callback runs in the parent process, so data isn't being passed back aside from the exit status of your child. You'll need to figure out some sort of IPC to notify the necessary details.

Although - I'd point out @names isn't a hash, so treating it like one is going to have strange behaviour :).

Have you considered threading as an alternative? Threads are good for shared memory operations passing keyed subprocesses is something it's good at.

Upvotes: 1

Related Questions