my $children_wanted = 6; my @job_queue = map { 'sleep ' . int rand 100 } 1 .. 140; my %job_of = (); while ( $children_wanted < scalar keys %job_of && @job_queue ) { my $job = go( shift @job_queue ); $job_of{ $job->{pid} } = $job; wait_on_jobs(); sleep 5; } wait_on_jobs() while %job_of; my $too_long = whatever(); sub wait_on_jobs { foreach my $job ( values %job_of ) { my $pid = $job->{pid}; if ( $pid == waitpid $pid, WNOHANG ) { delete $job_of{ $pid }; } if ( time() - $job->{start} > $too_long ) { kill 'TERM', $pid; } } return; } sub go { my ( $cmd ) = @_; my $pid = fork; if ( ! defined $pid ) { die "Can't fork: $!"; } if ( $pid ) { # parent return { pid => $pid, cmd => $cmd, start => time() }; } else { # child # close and exec and stuff } die 'unreachable code reached'; }