I don't think there's anything wrong with polling with waitpid, but I wonder if it can be avoided somehow. Perhaps you could create children with "open my $child_fh, '-|'" and have the parent use IO::Select to wait on them. The child does a fork,exec and a blocking wait (or just system), and it writes a status line back to the parent before it exits.
You may want to store a start time for each process and give it a time limit in case something hangs one day.
Looking at what you have, it seems as if it could be simpler. I haven't tested this, but it's how I'd start...
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'; }
In reply to Re: Using perl to manage child processes - critique my code.
by kyle
in thread Using perl to manage child processes - critique my code.
by FatDog
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |