Reputation: 40748
I would like to wait for two processes (or more) to finish, or a timer to count down. The timer countdown will be output in the terminal window. For example:
use warnings;
use strict;
use feature qw(say);
my $pid1 = fork();
if ( $pid1 == 0 ) {
runTask1();
exit 0;
}
my $pid2 = fork();
if ( $pid2 == 0 ) {
runTask2();
exit 0;
}
my $timer = startTimer();
say "Waiting for child processes..";
my $counter = 20;
my $i = 0;
while (1) {
my $pid = wait;
last if ( $pid == -1 );
if ( $pid == $timer ) {
$counter--;
say $counter;
$timer = startTimer();
} else {
say "Child with PID=$pid finished..";
$i++;
last if $i == 2;
}
}
say "Done.";
sub startTimer {
my $pidTimer = fork();
if ( $pidTimer == 0 ) {
sleep 1;
exit 0;
}
return $pidTimer;
}
sub runTask1 {
sleep 10;
exit 0;
}
sub runTask2 {
sleep 5;
exit 0;
}
My concern about this approach is that I create a forked sub process for the timer, which seems like overkill. Is this necessary, or is there a simpler way?
Upvotes: 2
Views: 2135
Reputation: 53478
Have a look at alarm()
- which triggers a kill signal ALRM
after the specified timeout. Which'll either just kill the process, or you can use:
$SIG{'ALRM'} = \&some_sub_to_handle_alarms;
alarm()
doesn't propagate to forked processes, so you can set it on your 'parent' so it just times out waiting for children.
You probably don't need to fork your pidTimer though - you can just have your main process sit in a loop.
The following demonstrates:
use strict;
use warnings;
use feature qw(say);
my $pid1 = fork();
if ( $pid1 == 0 ) { # Simulated Task 1
sleep 10;
exit 0;
}
my $pid2 = fork();
if ( $pid2 == 0 ) { # Simulated Task 2
sleep 5;
exit 0;
}
say "Waiting for child processes..";
my $counter = 20;
local $SIG{ALRM} = sub {
say --$counter;
alarm 1;
};
alarm 1;
while ((my $pid = wait) != -1) {
say "Child with PID=$pid finished..";
}
alarm 0;
say "Done.";
Outputs:
Waiting for child processes..
19
18
17
16
Child with PID=55240 finished..
15
14
13
12
11
Child with PID=55239 finished..
Done.
Upvotes: 5