On Tue, Sep 28, 2004 at 07:24:48AM +0900, leon breedt wrote: > i've seen discussion previously regarding the safety of timeout, > however, as i understand it, this usage is safe (@client is connected > socket) > > begin > timeout(30) do > line = @client.gets > end > rescue Timeout::Error > @client.close > end > > am i wrong? all the real work is done elsewhere once complete requests > have been received. That's true. The problem is that the timeout thread raises an exception asynchronously. In the above case your main work is just @client.gets, but if it were doing something more important, that work could be interrupted. In particular, even work within an 'ensure' block is interrupted. It's a common pattern to use 'ensure' to do cleanup work, but if the timeout occurs at just the wrong time, the cleanup may not be completed. This program demonstrates it: ---- 8< ------------------------ require 'timeout' def bar sleep(4) raise "wibble" # optional end def foo bar ensure puts "Cleanup started..." sleep(2) puts "Cleanup finished" end begin timeout(5) do foo end rescue Exception => e p e end ---- 8< ------------------------ You can try it both with and without the 'raise "wibble"' line. In both cases the cleanup code in the 'ensure' block does not complete. As a more realistic example, imagine some code like this: timeout(30) do File.open("mylog","a") do |f| ... do stuff end end File.open with a block does several things: 1. open the file 2. yield it to the block 3. close the file in an 'ensure' section If you were really unlucky, and the timeout occurred at exactly the same time as the 'ensure' section were being executed, then the file could remain open. At least, that's what I understand to be the crux of the issue. In many cases it's not going to be a major concern. You may be able to rewrite the code to make it safer by pushing the timeouts down to the lowest possible level. The above example could be rewritten safely as: File.open("mylog","a") do |f| timeout(30) do ... do stuff end end Regards, Brian.