#!/usr/bin/perl # vim: ts=2 sw=2 filetype=perl expandtab use warnings; use strict; use POE; use POE::Wheel::Run; use Test::More; sub DEBUG () { 0 } unless ( $ENV{RELEASE_TESTING} ) { plan skip_all => 'enable by setting RELEASE_TESTING'; } my $N = 60; diag "This test can take up to about ", int($N / 3), " seconds"; plan tests => $N + 2; POE::Session->create( inline_states => { _start => sub { my ($heap, $count) = @_[HEAP, ARG0]; $poe_kernel->sig(CHLD => 'sig_CHLD'); foreach my $n (1 .. $N) { DEBUG and diag "$$: Launch child $n"; my $w = POE::Wheel::Run->new( Program => sub { DEBUG and warn "$$: waiting for input"; ; exit 0; }, StdoutEvent => 'chld_stdout', StderrEvent => 'chld_stdin', ); $heap->{PID2W}{$w->PID} = {ID => $w->ID, N => $n}; $heap->{W}{$w->ID} = $w; } DEBUG and warn "$$: waiting 1 sec for things to settle"; $_[KERNEL]->delay(say_goodbye => 1); }, chld_stdout => sub { my ($heap, $line, $wid) = @_[HEAP, ARG0, ARG1]; my $W = $heap->{W}{$wid}; die "Unknown wheel $wid" unless $W; fail "stdout from $wid: $line"; }, chld_stderr => sub { my ($heap, $line, $wid) = @_[HEAP, ARG0, ARG1]; my $W = $heap->{W}{$wid}; die "Unknown wheel $wid" unless $W; if (DEBUG) { diag $line; } else { fail "stderr from $wid: $line"; } }, say_goodbye => sub { DEBUG and warn "$$: saying goodbye"; foreach my $wheel (values %{$_[HEAP]{W}}) { $wheel->put("die\n"); } $_[HEAP]{TID} = $poe_kernel->delay_set(timeout => $N); DEBUG and warn "$$: said my goodbyes"; }, timeout => sub { fail "Timed out waiting for children to exit"; $poe_kernel->stop; }, sig_CHLD => sub { my ($heap, $signal, $pid) = @_[HEAP, ARG0, ARG1]; DEBUG and diag "$$: CHLD $pid"; my $data = $heap->{PID2W}{$pid}; die "Unknown wheel PID=$pid" unless defined $data; my $W = $heap->{W}{$data->{ID}}; die "Unknown wheel $data->{ID}" unless $W; delete $heap->{PID2W}{$pid}; delete $heap->{W}{$data->{ID}}; pass("Child $data->{ID} exit detected."); unless (keys %{$heap->{W}}) { pass "all children have exited"; $poe_kernel->alarm_remove(delete $heap->{TID}); } } } ); $poe_kernel->run; pass("Sane exit");