I want to listen for connections for 2 seconds, then timeout. Do I have
to use the Timeout module?
~S
I want to listen for connections for 2 seconds, then timeout. Do I have
to use the Timeout module?
~S
From: “Shea M.” [email protected]
I want to listen for connections for 2 seconds, then timeout. Do I have
to use the Timeout module?
You could use select:
timeout_sec = 2.0
ios = select([@server], nil, nil, timeout_sec)
if ios
client = @server.accept
end
Note that you’ll probably want to put the socket into
nonblocking mode. It’s possible for select to return
“ready to read” and have accept still block, if the
client happens to disconnect in the small window
between the select and the accept.
Regards,
Bill
On Mar 28, 2006, at 9:48 AM, Shea M. wrote:
I want to listen for connections for 2 seconds, then timeout. Do I
have to use the Timeout module?
That will be the easiest way.
Timeout.timeout 2 do
Thread.start server.accept do |s| new_connection s end
end
–
Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant
On Mar 28, 2006, at 10:47 AM, Bill K. wrote:
client = @server.accept
end
Unfortunately this won’t accept connections for two seconds. If a
client connects at .5 seconds then immediately disconnects you’ll
need extra code to loop until you’ve consumed the full 2 seconds.
Note that you’ll probably want to put the socket into nonblocking
mode. It’s possible for select to return
“ready to read” and have accept still block, if the
client happens to disconnect in the small window between the select
and the accept.
Yuck, timeout will give a cleaner solution with less work.
–
Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant
From: “Eric H.” [email protected]
end
Oh, hey, cool. Using the thread there looks like it
ought to avoid the issue with Timeout firing in the
middle of ensure blocks and circumventing them?
I’ve been avoiding Timeout like “the plague” since
running into that behavior.
Regards,
Bill
Bill K. wrote:
Thread.start server.accept do |s| new_connection s end
endOh, hey, cool. Using the thread there looks like it
ought to avoid the issue with Timeout firing in the
middle of ensure blocks and circumventing them?I’ve been avoiding Timeout like “the plague” since
running into that behavior.
But the timeout won’t stop the thread.
$ cat timeout.rb
require ‘timeout’
th = nil
begin
Timeout.timeout 2 do
th = Thread.new do
loop {puts “in thread”; sleep 1}
end
end
rescue TimeoutError
puts “timeout!”
end
sleep 5
p th.alive?
$ ruby timeout.rb
in thread
in thread
in thread
in thread
in thread
true
Joel VanderWerf wrote:
end
Oh, hey, cool. Using the thread there looks like it
ought to avoid the issue with Timeout firing in the
middle of ensure blocks and circumventing them?I’ve been avoiding Timeout like “the plague” since
running into that behavior.But the timeout won’t stop the thread.
Ignore my last post. Not stopping the thread is probably exactly the
behavior that you want. The timeout affects only the server.accept call
(and the Thread.start). So this code is allowing 2 sec for a connection,
but no placing a limit on what happens after that.
I think it might be clearer to write it as
session = Timeout.timeout 2 do
server.accept
end
Thread.start(session) do |s| new_connection s end
but that is only my unconsidered opinion.
On Mar 28, 2006, at 12:23 PM, Bill K. wrote:
From: “Eric H.” [email protected]
On Mar 28, 2006, at 9:48 AM, Shea M. wrote:
I want to listen for connections for 2 seconds, then timeout. Do
I have to use the Timeout module?
That will be the easiest way.
Timeout.timeout 2 do
Thread.start server.accept do |s| new_connection s end
end
Ooh, I forgot the loop around Thread.start
Oh, hey, cool. Using the thread there looks like it
ought to avoid the issue with Timeout firing in the
middle of ensure blocks and circumventing them?I’ve been avoiding Timeout like “the plague” since
running into that behavior.
You’ve timed out, so that’s what’s supposed to happen
Its easy to know you’ve timed out though:
require ‘timeout’
Timeout.timeout 2 do
begin
ensure
begin
sleep
rescue Timeout::Error
puts ‘caught!’
end
end
end
But, don’t nest Timeout blocks without changing the raised
exception. Your code will eventually catch the wrong error and do
something bad.
class MyTimeout < Timeout::Error; end
Timeout.timeout 2, MyTimeout do end
–
Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant
From: “Joel VanderWerf” [email protected]
Timeout.timeout 2 do
But the timeout won’t stop the thread.
I don’t think it was supposed to. The #accept is
happening as an argument to Thread.start, so the thread
won’t be started until the connection is accepted.
The only teeny race condition I can see is if the
timeout fires after server.accept but before
Thread.start is invoked. That would seem to leak
the socket - but the GC would normally reclaim it
eventually (except in cases where it wouldn’t.
Regards,
Bill
From: “Joel VanderWerf” [email protected]
I think it might be clearer to write it as
session = Timeout.timeout 2 do
server.accept
endThread.start(session) do |s| new_connection s end
I think I’d do it that way too. (Probably adding a
rescue for Timeout::Error.)
I wonder if, there’s still any possible race condition
in this version.
session = Timeout.timeout 2 do
server.accept
# If timeout fires “here” would the socket be leaked?
# (eventual probable reaping by GC notwithstanding)
end
Not that I would lose much sleep over it. But I try
to write code without any possibility of race conditions
whenever possible.
I’m guessing the race condition does exist there. Anyone
know whether assignments are atomic with regard to
exceptions? E.g.
begin
Timeout.timeout 2 do
session = server.accept
# ^^^ atomic?
end
rescue Timeout::Error
end
Any possibility of the timeout interrupting the assignment
to “session” there? If assignment is atomic then we
should be able to avoid leaking the socket.
(Just wondering… not too worried about it in practical
terms with this particular example.)
Regards,
Bill
From: “Eric H.” [email protected]
Oh, hey, cool. Using the thread there looks like it
ought to avoid the issue with Timeout firing in the
middle of ensure blocks and circumventing them?I’ve been avoiding Timeout like “the plague” since
running into that behavior.You’ve timed out, so that’s what’s supposed to happen
Haha, yes… But it can be tricky…
Timeout.timeout 2 do
sleep 1.9
mutex.synchronize { @shared << “foo” }
end
…the timeout can fire in such a way that the
Thread#unlock in the ensure block of Thread#synchronize
is skipped - leaving the mutex locked.
I’ve been bitten by this… and it was pretty tough to
track down. (Of course, I was calling some harmless
looking method in the timeout block that just happened
to be using a mutex as part of its implementation…)
Regards,
Bill
Thread#unlock in the ensure block of Thread#synchronize
s/Thread/Mutex/g # :-o
From: “Shea M.” [email protected]
l_socket = l_listener.accept
rescue Timeout::Error
end #thread/do
I don’t think I have a race condition here, do I?
I’m not 100% sure myself, because I don’t know whether
this assignment:
l_socket = l_listener.accept
^^^
is atomic, or not.
However, I’m not suggesting to worry about it, either.
Practically speaking it seems unlikely to be a problem,
and ruby’s garbage collector will generally recover
orphaned file handles.
Regards,
Bill
Shea M. wrote:
I want to listen for connections for 2 seconds, then timeout. Do I have
to use the Timeout module?~S
My situation is more like this:
Thread.new do
begin
l_exit_status = false
l_listener = TCPServer.new( HOST, p_port )
l_socket = false
Timeout.timeout( 2 ) do
l_socket = l_listener.accept
end #timeout
#use socket
l_socket.put “send you requested data”
l_exit_status = true
rescue SocketError
$log.puts “socket error”
l_exit_status = false
rescue Timeout::Error
$log.puts “you only get 2 seconds to come and get the data”
l_exit_status = false
rescue Errno::EBADF
$log.puts “could not open connection”
l_exit_status = false
ensure
l_socket.close if l_socket
end #begin/rescue
l_exit_status
end #thread/do
I don’t think I have a race condition here, do I?
~S
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs