セールスポイント:
* STDOUT / STDERR やユーザデータの受け取りをコールバックで行えるようにしてあります。
* child process が die したときにも $pm->finish() を呼ぶようにしています。
* なにげにハンドルと変数代入のperl IO レイヤのサンプルにもなっています。
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use Data::Dumper;
use Carp qw(croak);
use Encode qw(decode_utf8);
use Parallel::ForkManager;
sub say { print $_[0], "\n"; }
our $N_CHILDREN = 5;
my $pm = Parallel::ForkManager->new($N_CHILDREN);
# callback when child process exit or die.
$pm->run_on_finish( sub {
my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_;
if (defined $data_structure_reference) {
#print Dumper($data_structure_reference);
print STDOUT Encode::decode_utf8($data_structure_reference->{'stdout'});
print STDERR Encode::decode_utf8($data_structure_reference->{'stderr'});
say "Client terminating with data => ". $data_structure_reference->{'i'};
}
say "EXCEPTION: child PID: $pid with $exit_code" if $exit_code ;
say "";
});
foreach my $i (0..9) {
my $pid = $pm->start and next;
my ($stdout, $stderr) = ('','');
$SIG{__DIE__} = sub { $pm->finish( -1, { i => $i, 'stdout'=>$stdout, 'stderr'=>$stderr } ); };
close STDOUT;
close STDERR;
open STDOUT, ">:scalar:utf8", \$stdout or $pm->finish(-1);
open STDERR, ">:scalar:utf8", \$stderr or $pm->finish(-1);
STDOUT->autoflush(1);
STDERR->autoflush(1);
say "Client $$ starting...";
croak "Client died" if $i % 2 == 0 ;
sleep 10; # do something useful instead!
$pm->finish( 0, { i => $i, 'stdout'=>$stdout, 'stderr'=>$stderr } );
}
$pm->wait_all_children;
say "Parent process after all child has finished";
__END__