Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Fork in Perl 5.8

Status
Not open for further replies.

user2base

Technical User
Oct 16, 2002
29
0
0
GB
I've found a script on the web that uses fork to run several pings in parallel. It works fine on a Linux box running perl 5.00x but it does not work on RedHat 8 with perl 5.8. Is it due to the new multi threading architecture in 5.8 ?
Moreover, I've read on this forum that you can not push results to an array within a fork because each child process is going to create a copy of this array: this tends to be confirmed when I tried to debug this under 5.8, however this script (that does push to an array) works very well on 5.00x

So how to have this working on 5.8 ?
Here is the script:
(PS: I have tried to do this using Parallel::ForkManager and I have the same issue.)


sub ping_a_host {
my $host = shift;
`ping -i 1 -c 1 $host 2>/dev/null` =~ /0 packets rec/ ? 0 : 1;
}

my %pid_to_host;
my %host_result;

sub wait_for_a_kid {
my $pid = wait;
return 0 if $pid < 0;
my $host = delete $pid_to_host{$pid}
or warn(&quot;Why did I see $pid ($?)\n&quot;), next;
warn &quot;reaping $pid for $host\n&quot;;
$host_result{$host} = $? ? 0 : 1;
1;
}

my @hosts = map &quot;10.0.1.$_&quot;, &quot;001&quot;..&quot;254&quot;;

for (@hosts) {
wait_for_a_kid() if keys %pid_to_host > 10;
if (my $pid = fork) {
## parent does...
$pid_to_host{$pid} = $_;
warn &quot;$pid is processing $_\n&quot;;
} else { # child does
## child does...
exit !ping_a_host($_);
}
}

## final reap:
1 while wait_for_a_kid();

for (sort keys %host_result) {
print &quot;$_ is &quot;, ($host_result{$_} ? &quot;good&quot; : &quot;bad&quot;), &quot;\n&quot;;
}


 
How does it not work under Perl 5.8? How does it fail and what is the error message? It ran for me under 5.6.1 and 5.8.0.

jaa
 
Actually I have slightly modified this script like this:
- using Net::ping (this should not make any difference)
- by pushing the result in an array within the last loop like this:

------------------------------------------
1 while wait_for_a_kid();
for (sort keys %host_result) {
if ($host_result{$_}){
push (@result, $_);
}
}
print &quot;at the end result = @result\n&quot;;
return @result;
------------------------------------------

It returns @result as empty even if I can see it equal to IP addresses that are pingable if I print its value within the fork loop it seems that this is effectively a &quot;copy&quot; that is used each time as the result of the print is:

at the end result =
result = 172.17.10.63
result = 172.17.10.70

Note the ordering.....


Actually I am now using Parallel::ForkManager to simplify the script but the result is the same (does not work on 5.8)
The script looks like:

------------------------------------------------
use Parallel::ForkManager;

my ($startip, $endip) = @_;
my @result;

my @octet = split (/\./, $startip);
my @hosts = map &quot;$octet[0].$octet[1].$octet[2].$_&quot;, &quot;$octet[3]&quot;..&quot;$endip&quot;;
my $ip;
my $pid;

$pm = new Parallel::ForkManager(10);

foreach $ip (@hosts) {
# Forks and returns the pid for the child:
$pid = $pm->start and next;
#... do some work with $data in the child process ...
if (ping_a_host($ip)){
push @result, $ip;
}
$pm->finish; # Terminates the child process
}

print @result;

------------------------------------------
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top