Newbie question regarding threads and system commands

Sorry if I’m bothering you all again… This is my first program that
runs
a) threads and b) system commands, so I apologize for being a newbie.
What
I’m trying to do is ping multiple parts of a site to help an tech
support
guy (me) in figuring out where a point of failure is at a remote
location.
The reason I’m using threads: I want it to be faster than me typing
across
multiple cmd windows. The problem: it’s taking 15+ seconds when it
works.
I’ve been tinkering now with it for a few days, and I either get the
program
to end in 1 second (killing the child threads before they are done) or I
get
the 15 second problem. I’m just not real sure where to put the
Thread.jointo make this run smoothly - nor am I sure that
thread.join is the solution.

Joel VanderWerf suggested mapping stuff, but I’m not doing this by IP
address (his solution the other day involved ping 192.168.1.#{i}) and I
couldn’t quite figure out how to modify his code to fit mine.

code (with some stuff obfuscated)

def pingsite(site, type)
result = ping -n 4 #{site}-#{type}-1.chomp
return result
end
puts “What site?”
sitelocation = gets.chomp
t0 = Time.now
data = “”
sitetype=[“something”, “somethingelse”, “again”, “more”, “otherstuff”]
sitetype.each do |type|
type=Thread.new do
puts pingsite(sitelocation, type)
end
type.join
end
#sitetype.join
t1 = Time.now
puts “Finished in #{t1 - t0} seconds”

Output:
Finished in 14.711 seconds

with sitetype.join uncommented and type.join commented, I get this:
What site?
0110
Finished in 1.051 seconds

Can someone explain to me what I’m doing wrong?

This is one possible solution, which seems to work fine (it takes 3.14
seconds on my system to ping 3 web sites). Bottom line: you need to keep
a list of the threads and join all of them in the calling code. Hope
this helps. I recommend that you get a copy of the “Pickaxe” book
(Programming Ruby: The Pragmatic Programmers Guide, 2nd edition) , which
has a very good section on threading and lots of examples. In the
meantime, you can read this from the first edition:

http://www.rubycentral.com/book/tut_threads.html

require ‘thread’

class SystemExecutor

Returns array [[cmd, response], [cmd, response], …]

def SystemExecutor.run(system_cmd_list)
thread_list = []
system_response_list = []
srl_mutex = Mutex.new

system_cmd_list.each do |cmd|
  thread_list << Thread.new do
    begin
      response = %x{ #{cmd} }
      srl_mutex.synchronize do
        system_response_list << [cmd, response]
      end
    rescue Exception => exc
      srl_mutex.synchronize do
        system_response_list << [cmd, exc]
      end
    end
  end
end

thread_list.each { |thr| thr.join }
system_response_list

end
end

puts “Starting ping”
start_time = Time.now
resp = SystemExecutor.run([‘ping www.ruby-forum.org’, ‘ping
www.sourceforge.net’, ‘ping www.google.com’])
elapsed_time = Time.now - start_time

resp.each do |cmd, resp|
puts “Command: #{cmd}”, ‘-’ * 20
puts “Response:\n”, ‘-’ * 20, “#{resp}”
end

puts “Elapsed time: #{elapsed_time} seconds.”

Maybe there’s something wrong with my system here at work then…
because
this took 11.something seconds to run on my machine. I’ll test again
from
home (both xp pro systems)

As it turns out, your program runs fine (<4 seconds) if I change the
ping
destinations to something on the internal network. Looks like a router
is
misconfigured somewhere. Thanks!

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs