Using backticks in forked child

D

deoquinn

Hello all, I have a a need to use backticks in a forked child while
running many simultaneous children (on Windows). This is a pinging
application, so, I am pinging multiple hosts and capturing their ping
response time as shown below.... The problem is that I can *only* get
this to work if I move the 'child' code to another script and then
'exec(....)' that script, which is turning out to be *very* expensive
and slow... If I run it as coded, it hangs after the first (sometimes
first couple of) forks. Do I need to do something with STDIN/STDOUT
(or something else) in the child here? I have tried several different
ways of doing this (including using Net::ping ( with external protocol
and HiRes ) but it didn't perform very well nor behave like I wanted -
plus, I will be running this on multiple systems and do not want to
have to install more modules everywhere and keep them up to date, so,
I'd like to leave that out)...

So... The question is... How do the system calls happen in the
forked children and why is such a call hanging the script? The
platform is Windows Server 2003 and the perl vers is 5.8.8 Build 820.

Thanks to any responders....

foreach $host ( sort { uc($a) cmp uc($b) } keys %hosts ) {
my $pid;
# throttle back the spawning to limit impact on system
if ( $throttle++ > 20 ) { sleep 5; $throttle = 0; }
FORK: {
if ( $pid = fork ) {
# Parent
# Harvest a few finished children if existent....
waitpid(-1,WNOHANG);
next; # go get next host and fork again...
}
elsif ( defined $pid ) {
# Child
my $avg = -1;
for ( my $i = 1; $i < 4 && $avg == -1; $i++ ) {
$wait = $i*1000;
foreach ( reverse (`ping -w 1000 -n 1 $host`) )
{ ###### BACKTICKS HERE
last if $avg != -1 || $? > 0;
# Get the avg ping response time only - implied ping
failure is $avg is not changed from -1
if ( m/Average\s=\s/ ) { ( $avg = $_ ) =~ s/^.*?Average\s=
\s(\d+).*\n*$/$1/ }
}
}
print "\Child: Average $host - $avg ms\n";
}
elsif ( $! == EAGAIN ) {
# Sleep a little and Harvest orphaned children before retrying
fork....\n";
sleep 5;
wait();
redo FORK;
}
else { die "Unrecoverable Fork Error: $!" }
} # end FORK Label
} # end FOREACH loop
exit;
 
D

deoquinn

Sorry; forgot the following 2 'Use' Stmts for the listed code...
use Errno qw(EAGAIN);
use POSIX ":sys_wait_h";

Also, perhaps a simpler test script would be....

1) Create a file named fork_sleeper.pl with the following code in
it...

use Time::HiRes qw[time];
sleep 3;
print "Time(".time().") Child: Done Sleeping\n";
exit 0;

2) Use the following code in the same dir as the fork_sleeper.pl file
(NOTE: TimeHiRes is not required, but you won't get much
differentiation in your time stamps if you don't use it... See output
below the code....... Uncomment the exec() or the backticks line of
code to test...

use Errno qw(EAGAIN);
use POSIX ":sys_wait_h";
use Time::HiRes qw[time];

$sleeper = (split /(.*)\\.*?$/,$0)[1] . "\\fork_sleep.pl";
my $i;
for ($i = 0; $i<10; $i++ ) {
my $pid;
print "$i Time(".time().") Parent: Forking\n";
FORK: {
if ($pid = fork()) { next; }
elsif ( defined $pid ) {
print "$i Time(".time().") Child: About to sleep...\n";
# `$sleeper`; ##### USE THIS LINE TO TEST WITH
BACKTICKS....
# exec("$sleeper"); ##### USE THIS LINE TO TEST WITH EXEC().....
exit;
}
elsif ( $! == EAGAIN ) {
print "$i Time(".time().") Parent: Recoverable Error '$?'
'$!'\tHarvest orphaned children and retry fork....\n";
sleep 5;
wait();
print "$i Time(".time().") Parent: Redoing Fork\n";
redo FORK;
}
else { die "Time(".time().") Unrecoverable Fork Error: $!" }
}
}
exit 0;


Output with BackTicks....
0 Time(1185503292.10938) Parent: Forking
1 Time(1185503292.14443) Parent: Forking
2 Time(1185503292.17593) Parent: Forking
3 Time(1185503292.21377) Parent: Forking
0 Time(1185503292.2512) Child: About to sleep...
Terminating on signal SIGINT(2)
That was the last line... it never went further so I hit CTRL-C to
kill it....

Output using exec()....
0 Time(1185503510.3125) Parent: Forking
1 Time(1185503510.36191) Parent: Forking
2 Time(1185503510.39841) Parent: Forking
3 Time(1185503510.43181) Parent: Forking
0 Time(1185503510.45847) Child: About to sleep...
1 Time(1185503510.46419) Child: About to sleep...
2 Time(1185503510.46862) Child: About to sleep...
4 Time(1185503510.4979) Parent: Forking
5 Time(1185503510.531) Parent: Forking
6 Time(1185503510.56713) Parent: Forking
5 Time(1185503510.58752) Child: About to sleep...
4 Time(1185503510.59228) Child: About to sleep...
3 Time(1185503510.59585) Child: About to sleep...
7 Time(1185503510.62381) Parent: Forking
8 Time(1185503510.65922) Parent: Forking
9 Time(1185503510.70196) Parent: Forking
6 Time(1185503510.73913) Child: About to sleep...
7 Time(1185503510.74363) Child: About to sleep...
8 Time(1185503510.74823) Child: About to sleep...
9 Time(1185503510.79715) Child: About to sleep...
Time(1185503518.28125) Child: Done Sleeping
Time(1185503518.32813) Child: Done Sleeping
Time(1185503518.375) Child: Done Sleeping
Time(1185503518.42188) Child: Done Sleeping
Time(1185503518.45313) Child: Done Sleeping
Time(1185503518.51563) Child: Done Sleeping
Time(1185503518.54688) Child: Done Sleeping
Time(1185503518.625) Child: Done Sleeping
Time(1185503518.64063) Child: Done Sleeping
Time(1185503518.67188) Child: Done Sleeping
 
T

TonyV

Hello all, I have a a need to use backticks in a forked child while
running many simultaneous children (on Windows).

I've run into this too, forked processes working fine until you throw
a system call using backticks in the mix, then they die, and I don't
know how to correct it.

Anyone else know what's happening?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top