Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Forkin around

by gnu@perl (Pilgrim)
on Dec 11, 2002 at 21:49 UTC ( [id://219186]=perlquestion: print w/replies, xml ) Need Help??

gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

I have a forked ping program (mostly lifted from www.stonehenge.com, thanks merlyn). Anyway, I have modified his code to use Net::Ping and log the results to a file.

The problem I am having is this, I need the part that loads the array @hosts to only be executed in the parent not the child, but the fork comes below in the block that depends on @hosts being populated. The problem is that the loading of @hosts is being done in every child. Not only is this not efficient, but I am getting multiple reports of bad ip's written to the log file.

How can I, prior to having $pid set in the fork, make the block that loads @hosts execute only in the parent?

#!/usr/bin/perl -w use strict; use Net::Ping; my $source_file = (shift || "/tmp/ping_list.txt"); my $good_out = "/tmp/good_ips.txt"; my $bad_out = "/tmp/bad_ips.txt"; my %pid_to_host; my %host_result; my @hosts; $|++; open(GOOD,">$good_out") or die "Cannot open output file $good_out: $!\n"; open(BAD,">$bad_out") or die "Cannot open output file $bad_out: $!\n"; open(IPS,"$source_file") or die "Cannot open source file $source_file: $!\n"; for (<IPS>) { chomp; s/ *//; s/\cM//; if ($_ =~ m/^\d+\.\d+\.\d+\.\d+$/) { push(@hosts,$_); } else { print BAD "$_ : NOT A VALID IP ADDRESS\n"; } } for (@hosts) { wait_for_a_kid() if keys %pid_to_host > 50; if ( my $pid = fork ) { # parent $pid_to_host{$pid} = $_; } else { # child exit !ping_a_host($_); } } 1 while wait_for_a_kid(); for (sort keys %host_result) { print GOOD "$_\n" if ($host_result{$_}); print BAD "$_\n" if (!$host_result{$_}); } sub ping_a_host { my $host = shift; my $p = Net::Ping->new('tcp',5); $p->ping($host) ? 1 : 0; } sub wait_for_a_kid { my $pid = wait; return 0 if $pid < 0; my $host = delete $pid_to_host{$pid} or warn("Why did I see $pid ($?)\n"), next; $host_result{$host} = $? ? 0 : 1; 1; }

Replies are listed 'Best First'.
Re: Forkin around
by tall_man (Parson) on Dec 12, 2002 at 20:19 UTC
    I see that this question has not been answered for a day, so perhaps I am not the only one confused by it. Perhaps you could clarify what you are asking?

    How can I, prior to having $pid set in the fork, make the block that loads @hosts execute only in the parent?

    Of course you know that prior to the fork the children do not exist, and that none of the work that was done before the fork takes place is redone by the children. At child process begins life with an exact duplicate of the state of the parent. So the @hosts array was loaded by the parent and only by the parent.

      That's exactly what was blowing my mind. I could not comprehend how the 'print BAD "$_ : NOT A VALID IP ADDRESS\n";' was being executed over and over again for each child process that was being spawned. If I took the 'BAD' filehandle out and just let the print go to STDOUT I only got one iteration to my screen, but the moment I tried to print it to the BAD FH I kept getting multiple instances of the same data from the children.

      At first I assumed that the reason I did not see multiples when printing to STDOUT was that STDOUT was disasociated in the children. That conclusion was incorrect.

      It turns out that each child process was indeed sending the data to the output file attached to 'BAD'. But not in any way that was immediately apperent to me. What was happening was that I did not turn on autoflushing for those FH's. When the children recieved dupes of the open FH's and then closed, the FH's were flushed. So, essentially each child was flushing the FH and the output went were it was supposed to, the file.

      I added autoflush for each output FH and the problem went away. I just popped in here to update this when I saw your response.

      Thanks for your input though, I was starting to wonder why I had no response.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://219186]
Approved by particle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-19 01:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found