Also have a look at Parallel::Forker, I use it all the time it works great exactly as you expect and has advantages over Parallel::ForkManager like child process signalling.
use Parallel::Forker;
my $forker = Parallel::Forker->new(use_sig_child => 1, max_proc => 8);
$SIG{CHLD} = sub { Parallel::Forker::sig_child($forker); };
$SIG{TERM} = sub { $forker->kill_tree_all('TERM') if $forker && $forke
+r->in_parent; };
for (1..10) {
$forker->schedule(run_on_start => sub {
# do child process code here
})->ready();
}
# wait for all child processes to finish
$forker->wait_all();
hth