JamesNC has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to figure out how to implement threads to ping about 10-20 hosts at a time. Win32(XP) Perl v5.8.0 built for MSWin32-x86-multi-thread
use threads; use threads::shared; use strict; my $wait = 500; my @up: shared; my $th; my @down: shared; my @list = qw ( www.apple.com www.perl.org www.ibm.com www.coke.com ww +w.oracle.com www.hp.com ); foreach(@list){ $th = threads->create("ping","$_"); # $th->join; # new thread is NOT created until join # not what I want! } # This works... unless one of the threads finishes too # soon... then the app dies... $th->join; print @up; print @down; sub ping { my $ip = shift; my @rv = `ping -n 1 -w $wait $ip`; foreach(@rv){ push @up, "$ip up\n" if /\(0% loss\)/; push @down, "$ip down\n" if /\(100% loss\)/; } }
Ok, the problem is that if I join in the block where the threads get created... it waits for each process to finish. If I join after the create threads... it works... BUT ONLY IF all the threads finish in order... And, if I don't join at all... I don't get anything I have tried the async method, and got the same results. Are all the threads dependant on each other? If you have to wait on each thread to finish... what is the use in threads?

Replies are listed 'Best First'.
Re: Using threads with Ping
by pg (Canon) on Jan 31, 2003 at 04:50 UTC
    join is a blocked call, so it will not return until the child thread is joined, i.e. returned.

    foreach(@list){ $th = threads->create("ping","$_"); # $th->join; # new thread is NOT created until join # not what I want! }
    This does not work, because it will only go to the next iteration, i.e. create next child thread, when the previous one returned.

    What you can do is to store all the child thread handlers in an array:
    foreach(@list){ push @childs, threads->create("ping","$_"); } ... foreach $child (@childs){ $child->join(); }
      Wow.. it works perfectly now :-) Thank you so very much! I see all the threads get created.. and now this time.. they join in different orders! Very fast too.. For anyone that interested, here is the working code with pg's fix:
      use threads; use threads::shared; use strict; my $wait = 500; my @up: shared; my $th; my @childs; my $child; my @down: shared; my @list = qw ( www.apple.com www.perl.org www.ibm.com www.coke.com www.oracle.com www.hp.com ); foreach(@list){ push @childs, threads->create("ping","$_"); } foreach $child (@childs){ $child->join(); } print @up; print @down; sub ping { my $ip = shift; my @rv = `ping -n 1 -w $wait $ip`; foreach(@rv){ push @up, "$ip up\n" if /\(0% loss\)/; push @down, "$ip down\n" if /\(100% loss\)/; } }
Re: Using threads with Ping
by submersible_toaster (Chaplain) on Jan 31, 2003 at 06:28 UTC

    ++JamesNC for believing pg (who also gets ++) and making the code-change, and actually listening. Compared to an unnamed visitors Possible bug with threads.



    I can't believe it's not psellchecked
Re: Using threads with Ping
by derby (Abbot) on Jan 31, 2003 at 13:55 UTC
    A very informative node on threads (++ to all).

    Am I just being too sarcastic to see the value in spawning of a bunch of threads that just do a backtick operation? Don't get me wrong, I see the general value in the question and answers about thread spawning and joining but would this be a proper monks node without someone questioning the given script. Is there something funky about perl on Win32 that I'm missing (like backticks don't fork/exec). Or more general, is there any value in spawing threads that will just fork/exec a cmd.

    My first inclination is that no, there is no value in that. You should either junk the thread overhead and just stick with fork/exec (and not use backticks because there's overhead in that with a shell coming into the equation) or find some "thread-safe/thread-aware" way to ping (is Net::Ping thread-safe?).

    However, if this is just an exercise in threading and is not going to be used in the real world - then nevermind.

    -derby

      It was an exercise and I plan on using it in the real world. I use this in a CGI based interface. Net::Ping has to run as someone with Administrator on IIS which was not allowed.(Yes I even tried commenting out that line...) I read that using threads was much more memory efficent than using fork. I am not qualified to debate you on which method is faster or more efficent, or better (fork/threads). Why don't you post that question to the Monks?