You can use a hash to keep track of the children you have.
$children{$pid} = 1; # On creation.
delete($children{$pid}); # On reaping.
keys(%children) # Lists existing children.
So all that's left is waiting for all the children to complete, and there's already an example of that in AnyEvent->child
's documentation.
All together, we get
my $done = AnyEvent->condvar;
my %children;
my $spawner;
sub ae_sleep {
my ($dur) = @_;
my $done = AnyEvent->condvar;
my $t = AnyEvent->timer(after => $dur, cb => sub { $done->send });
$done->recv;
}
sub kill_children {
for my $sig (qw( HUP QUIT INT KILL )) {
last if !%children;
kill($sig => $_) for keys(%children);
ae_sleep(1);
}
}
$SIG{QUIT} = sub {
$spawner = undef; # Stop creating new children.
kill_children(); # Kill existing children.
$done->recv; # Wait for children to be reaped.
exit(0);
}
sub create_child {
my $pid = ...;
$done->begin;
$children{$pid} = AnyEvent->child(
pid => $pid,
cb => sub {
my ($pid, $status) = @_;
delete($children{$pid});
warn "pid $pid exited with status $status";
$done->end;
},
);
}
$spawner = AnyEvent->timer(
after => 0,
interval => 5,
cb => \&create_child.
);
AnyEvent->condvar->recv; # Wait "for ever".