Timeout::Errorに注意

rubyのTimeout::Errorにはまってしまったので、記録しておきます。

net/httpを使ってWebサーバに接続するデーモンプログラムを書いていました。例外はすべてキャッチするつもりでrescueを書いていました。

require 'net/http'
begin
  Net::HTTP.start("www.foo") do |http|
    ...
  end
rescue =>e  # エラータイプを省略
  ...
end

しかし、net/httpではTimeout::Error例外を発生させるではありませんか。

しかもさらに悪いことに、接続先のサーバはめったにタイムアウトしないのでTimeout::Errorが発生することに気がつきませんでした。

いろいろ調べてみると、

  • rescueはエラータイプを省略するとStandartErrorのサブクラスの例外を捕捉する
  • Timeout::ErrorはInterruptを継承したクラスでStanderErrorには属していない
  • net/httpなどのライブラリはtimeout.rbを使っている
  • gemでインストールしているライブラリもtimeout.rbを使っている

今後、例外をすべてキャッチするつもりでコーディングするときは、下記のテンプレートを使っていこうと思います。

begin
  ....
rescue Timeout::Error, StandardError =>e
end