Non-blocking waiting, rerun on failure
In this example we have a list of tasks we need to do. The user can supply the number of child processes that will deal with the tasks. Each child process generates a random number to wait to imitatet the work time and a random number as the exit code.
The parent monitors the child processes. If one of them exits with a non-zero error code the parent re-runs that job with another child process until all the tasks are done.
use strict;
use warnings;
use Time::HiRes qw(sleep);
use POSIX ':sys_wait_h';
main();
sub main {
my ($workers) = @ARGV;
die "Usage: $0 WORKERS\n" if not defined $workers;
#my @tasks = 'a' .. 'z';
my @tasks = 'a' .. 'd';
my %process;
while (1) {
if (@tasks and scalar(keys %process) < $workers) {
my $task = shift @tasks;
my $pid = fork();
die 'Failed to fork' if not defined $pid;
if ($pid == 0) {
my $exit_code = int rand(3);
my $sleep_time = rand(5);
print "Child process Task: $task PID $$ will sleep for $sleep_time and then exit with code $exit_code\n";
sleep $sleep_time;
exit $exit_code;
}
$process{$pid} = $task;
next;
}
my $pid = waitpid(-1, WNOHANG);
if ($pid > 0) {
my $exit_code = $?/256;
my $task = delete $process{$pid};
print "Child process $pid task $task finished with exit code $exit_code\n";
if ($exit_code > 0) {
unshift @tasks, $task;
}
next;
}
sleep 0.1;
last if not %process;
}
}
Child process Task: a PID 128387 will sleep for 3.71995377981634 and then exit with code 2
Child process Task: b PID 128388 will sleep for 0.137503658640838 and then exit with code 0
Child process Task: c PID 128389 will sleep for 3.57264931009681 and then exit with code 1
Child process 128388 task b finished with exit code 0
Child process Task: d PID 128390 will sleep for 0.940422063447244 and then exit with code 0
Child process 128390 task d finished with exit code 0
Child process 128387 task a finished with exit code 2
Child process 128389 task c finished with exit code 1
Child process Task: a PID 128391 will sleep for 3.09917882712156 and then exit with code 2
Child process Task: c PID 128392 will sleep for 1.52811677938857 and then exit with code 2
Child process 128392 task c finished with exit code 2
Child process Task: c PID 128393 will sleep for 1.21268558593997 and then exit with code 0
Child process 128393 task c finished with exit code 0
Child process 128391 task a finished with exit code 2
Child process Task: a PID 128394 will sleep for 2.05004244389542 and then exit with code 2
Child process 128394 task a finished with exit code 2
Child process Task: a PID 128395 will sleep for 4.95541832222202 and then exit with code 0
Child process 128395 task a finished with exit code 0