in reply to Re^2: Parallel::ForkManager and wait_all_children
in thread Parallel::ForkManager and wait_all_children

If you exec another program, the running perl is terminated so can't send the alarm.

alarm causes the system to send SIGALRM to the current process.

Don't you have to use system() and kill the child process if it times out?

You can't kill a child if you're waiting for it to exit using system, so you'd have to replace system.

use IPC::Open3 qw( open3 ); use POSIX qw( WNOHANG ); use constant TIMEOUT => 60; sub wait_for_test_to_end { my ($pid) = @_; my $abs_timeout = time() + TIMEOUT; while (1) { return if waitpid($pid, WNOHANG) > 0; last if time() > $abs_timeout; sleep(1); } kill(ALRM => $pid); $abs_timeout = time() + 15; while (1) { return if waitpid($pid, WNOHANG) > 0; last if time() > $abs_timeout; sleep(1); } kill(KILL => $pid); waitpid($pid, 0); } while (1) { for my $runCommand (@runArray) { $forkMgr->start($runCommand) and next; my $pid = open3('<&STDIN', '>&STDOUT', '>&STDERR', "/usr/localcw/opt/patrol/nagios/libexec/$runCommand"); wait_for_test_to_end($pid); $forkMgr->finish($? & 0x7F ? 0x80 | ($? & 0x7F) : $? >> 8); } $forkMgr->wait_all_children; sleep 10; }

And you're back to having a useless process between the manager than the test.

On the plus side, you can use more complex conditions than a simple timeout. You can also forcibly kill the process if it doesn't respond to SIGALRM as the above demonstrates.

Replies are listed 'Best First'.
Re^4: Parallel::ForkManager and wait_all_children
by rgren925 (Beadle) on May 13, 2015 at 22:13 UTC

    Thanks all for the replies.

    I've tried to synthesize the different approaches.

    To flesh this out a bit, I'm planning on using callbacks (run_on_wait) to manage notifying/killing a hung process. Using the alarm(TIMEOUT) doesn't really solve my problem. If I set the timeout to 60, no other processes will run until that 60 seconds has elapsed as the wait_all_children still isn't satisfied.

    wait_for_available_procs (which was newer than my version of Parallel::ForkManager--so I upgraded) didn't seem to make any difference.

    The callbacks indicate that everything stalls until the looping test4.sh script is killed.

    use strict; use warnings; use Parallel::ForkManager; use constant TIMEOUT => 60; my @runArray = ("test1.sh", "test2.sh", "test3.sh", "test4.sh", "test5 +.sh"); my ($pid, $exitCode, $ident); my $forkMgr = Parallel::ForkManager->new(3); $forkMgr->run_on_start( sub { ($pid, $ident) = @_; print "Started ==> $ident\n"; } ); $forkMgr->run_on_finish( sub { ($pid, $exitCode, $ident) = @_; print "Ended ==> $ident\n"; } ); while (1) { for my $runCommand (@runArray) { $forkMgr->start($runCommand) and next; alarm(TIMEOUT); system("/usr/localcw/opt/patrol/nagios/libexec/$runCommand") o +r die ("exec: $!\n"); } $forkMgr->wait_all_children; sleep 10; } exit;