Using backticks in forked child

Discussion in 'Perl Misc' started by deoquinn@yahoo.com, Jul 27, 2007.

  1. Guest

    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;
    , Jul 27, 2007
    #1
    1. Advertising

  2. Guest

    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
    , Jul 27, 2007
    #2
    1. Advertising

  3. TonyV Guest

    On Jul 26, 7:38 pm, wrote:
    > 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?
    TonyV, Jul 27, 2007
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    8,687
    Sebastian Scheid
    Aug 25, 2005
  2. Donn Cave
    Replies:
    2
    Views:
    504
    MrEntropy
    Jul 15, 2005
  3. Noam Noam
    Replies:
    3
    Views:
    126
    Noam Noam
    Oct 30, 2007
  4. Zbigniew Fiedorowicz

    Getting STDERR from forked child processes?

    Zbigniew Fiedorowicz, Feb 5, 2004, in forum: Perl Misc
    Replies:
    2
    Views:
    152
    Aaron Sherman
    Feb 5, 2004
  5. Moritz Karbach

    How to kill a forked child process...

    Moritz Karbach, Jun 17, 2005, in forum: Perl Misc
    Replies:
    11
    Views:
    396
    Moritz Karbach
    Jun 20, 2005
Loading...

Share This Page