Empty page. Click on 'Edit text of this page' below, or try
the home page.
#!/usr/pin/perl
# This example demonstrates setting up a child process based on a coderef
# using POE::Wheel::Run and installing a nested kernel inside of it which talks
# back and forth with the parent process via POE::Filter::Reference.
#
# The worker is comically simple, it just increments a counter.
#
# It took me some time to figure this out so I hope others find it useful.
# It could probably be simplified somewhat.
use strict;
use warnings;
use POE qw(Wheel::Run Wheel::ReadWrite Filter::Reference);
sub worker {
POE::Kernel->stop();
print STDERR "Worker forked\n";
POE::Session->create(
inline_states => {
_start => sub {
my ($kernel, $heap) = @_[KERNEL, HEAP];
$heap->{client} = POE::Wheel::ReadWrite->new(
InputHandle => \*STDIN,
OutputHandle => \*STDOUT,
InputEvent => 'worker_inside_input',
ErrorEvent => 'worker_inside_error',
Filter => POE::Filter::Reference->new(),
);
$kernel->sig(TERM => '_stop');
print STDERR "Worker session started\n";
},
worker_inside_input => sub {
my ($heap, $kernel, $input) = @_[HEAP, KERNEL, ARG0];
print STDERR "got input $input->[0]\n";
my $output = [$input->[0] + 1];
$heap->{client}->put($output);
},
worker_inside_error => sub {
my ($heap, $op, $code) = @_[HEAP, ARG0, ARG1];
warn "worker inside error: $op $code";
},
}
) or die "worker: can't POE::Session->create: $!";
POE::Kernel->run();
print STDERR "Worker done\n";
return;
}
sub worker_error {
my ($hash, $op, $code, $handle) = @_[HEAP, ARG0, ARG1, ARG4];
if ($op eq 'read' and $code == 0 and $handle eq 'STDOUT') {
warn "child has closed output";
delete $hash->{worker};
}
}
sub worker_stdout {
my ($heap, $kernel, $value) = @_[HEAP, KERNEL, ARG0];
$heap->{count} = $value->[0];
print "worker responded: " . $heap->{count} . "\n";
$kernel->yield('next_cmd');
}
sub worker_stderr {
my ($heap, $txt) = @_[HEAP, ARG0];
print "worker_stderr: $txt\n";
}
POE::Session->create(
inline_states => {
_start => sub {
my ($kernel, $heap) = @_[KERNEL, HEAP];
$heap->{worker} = POE::Wheel::Run->new(
Program => \&worker,
ErrorEvent => 'worker_error',
StdoutEvent => 'worker_stdout',
StderrEvent => 'worker_stderr',
StdioFilter => POE::Filter::Reference->new(),
) or die "$0: can't POE::Wheel::Run->new";
$heap->{count} = 0;
$kernel->yield('next_cmd');
},
worker_stdout => \&worker_stdout,
worker_stderr => \&worker_stderr,
worker_error => \&worker_error,
next_cmd => sub {
my ($kernel, $heap) = @_[KERNEL, HEAP];
if ($heap->{count} > 3) {
$heap->{worker}->kill('TERM');
}
else {
my $input = $heap->{count};
$heap->{worker}->put([$input]);
}
},
}
) or die "$0: POE::Session->create failed $!";
POE::Kernel->run();
exit 0;