gethostbyname で timeout できない
timeout は Thread で実現されているため、C レベルで停止してしまう (Threadの切替えが発生しない)処理に対しては効果がありません。
以下の例では、gethostbyname(およそ0.6秒処理に時間がかかっている) が終了し た直後((A)の箇所)で TimeoutError 例外があがっています。
require 'timeout'
require 'socket'
start = Time.now
begin
timeout(0.1) {
p TCPSocket.gethostbyname("www.ruby-lang.org")
# (A)
}
ensure
p Time.now - start
end
=> ["helium.ruby-lang.org", [], 2, "210.251.121.214"]
0.689331
/usr/local/lib/ruby/1.6/timeout.rb:37: execution expired (TimeoutError)
from -:6:in `timeout'
from -:6
Rubyでかかれたリゾルバを利用するという回避策があります。
require "resolve-replace" すると、resolve.rb で定義された、
リゾルバが利用されるようになります。
cygwin や mingw では以下もダメという報告があります。同じ理由かも知れ ません(本来、入力待ちの状態では入力を監視しつつThread切替えを行うので 大丈夫なはずなのですが)
require 'timeout'
begin
timeout(5) do
$stdin.gets
end
rescue TimeoutError
print "timeout\n"
end