Breaking Out Of A Loop

M

Mike

I'm somewhat new to Ruby and have been playing around with some very simple
socket code (starting the script and then telnetting to the box on the port
specified). I wanted to allow it to accept more than one request at a time
so I added some threads. However, now that I've added some thread code, I
can't get the script to end properly (I guess "as expected" is more
appropriate). Here's some code:

require 'socket'
p = 3333
threads = []
s = ''

server = TCPServer.new('0.0.0.0', p)

while (session = server.accept)
threads << Thread.new(session) do |ts|
ts.print "What's your name?\r\n"
puts "Request: #{s = ts.gets.chomp!}"
ts.print "\r\nHello #{s}, thanks for stopping by\r\n\r\n"
ts.close
end
break if s == 'close'
end

How it behaves is that if you connect and then send the string 'close', it
accepts it and handles it as a normal request with any other string.
However, on the connection following the one with 'close', it will then
terminate the script. I'm of the impression that it *should* close it as
soon as I send 'close', but this is obviously not the case. Without the
threading, it was working fine:

require 'socket'
p = 2222
server = TCPServer.new('0.0.0.0', p)

while (session = server.accept)
session.print "What's your name?\r\n"
puts "Request: #{s = session.gets.chomp!}"
session.print "\r\nHello #{s}, thanks for stopping by\r\n\r\n"
session.close
if s == 'close'
break
end
End

This obviously needed to be modified some since the break would be inside of
the thread block and wouldn't terminate the while loop. That's ultimately
why I'm defining s outside of the loop so that the threads have access to it
and can use it as an ugly global that I was hoping would be read and used to
close the while loop as the thread goes to it's 'end'.

Any insight would be appreciated - pardon the ugly code, this is my first
real foray into sockets, threads and ruby :)
 
E

Edward Faulkner

--YZ5djTAD1cGYuMQK
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

while (session = server.accept)
threads << Thread.new(session) do |ts|
ts.print "What's your name?\r\n"
puts "Request: #{s = ts.gets.chomp!}"
ts.print "\r\nHello #{s}, thanks for stopping by\r\n\r\n"
ts.close
end
break if s == 'close'
end

You have a race condition. "s == 'close'" is getting evaluated before
"s = ts.gets.chomp!". That's why the program doesn't exit until the
next time through the loop.

In this solution, the child thread causes the main thread to raise an
exception, breaking out of the accept() call:

require 'socket'
p = 3333
server = TCPServer.new('0.0.0.0', p)

loop do
begin
Thread.new(server.accept) do |ts|
ts.print "What's your name?\r\n"
puts "Request: #{s = ts.gets.chomp!}"
if s == 'close'
Thread.main.raise "Closing"
else
ts.print "\r\nHello #{s}, thanks for stopping by\r\n\r\n"
end
ts.close
end
rescue
puts "Exiting"
break
end
end

regards,
Ed

--YZ5djTAD1cGYuMQK
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFEBbpmnhUz11p9MSARAjZGAKCEQDpWdsdrScg9zuX4V2G43q8hYQCfXkqk
pKpfsOlzLge6OtCyDWuHmYA=
=6t2e
-----END PGP SIGNATURE-----

--YZ5djTAD1cGYuMQK--
 

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,768
Messages
2,569,574
Members
45,049
Latest member
Allen00Reed

Latest Threads

Top