From: Yusuke ENDOH Date: 2009-10-03T15:19:17+09:00 Subject: [ruby-dev:39421] exception from open-uri 遠藤です。 open-uri を使って定期的に Web ページを取得するプログラムを走らせて いると、実にさまざまな例外が投げられうることに気がつきました。 今のところ経験したことがあるのは以下の 7 つです (経験した順) 。 - Errno::ETIMEDOUT - OpenURI::HTTPError - Errno::ECONNRESET - Timeout::Error - EOFError - Errno::EHOSTUNREACH - SocketError そこで質問です。 1) open-uri が投げうる例外は他にあるでしょうか (Errno::* はいくらでも ありそうですが) 。 2) この中で本来投げられるべきでない例外はないでしょうか。EOFError は 少し怪しいと思っています。バグだとしても Net::HTTP か Timeout のバグ だと思いますが。ちなみに再現させる方法はもちろんわかりません。 3) この状況に対して、open-uri のユーザはどのように対処することが要求 されているのでしょうか。4 つ思いつきました。 A. StandardError を rescue してまとめて対処する B. open-uri が投げうる例外をすべて把握し、個々に対処するコードを書く C. そもそも robust 性が要求されるプログラムで open-uri や Net::HTTP を使うことが想定されていないので、使ってはいけない D. そもそも robust 性が要求されるプログラムで Ruby を (略) ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux] で申し訳ないのです が、それぞれの例外が投げられたときのトレースを以下に貼り付けます。 /usr/lib/ruby/1.8/net/http.rb:560:in `initialize': Connection timed out - connect(2) (Errno::ETIMEDOUT) from /usr/lib/ruby/1.8/net/http.rb:560:in `open' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/timeout.rb:53:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:93:in `timeout' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/net/http.rb:553:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:542:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/open-uri.rb:277:in `open_http': 400 Bad Request (OpenURI::HTTPError) from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/net/protocol.rb:135:in `sysread': Connection reset by peer (Errno::ECONNRESET) from /usr/lib/ruby/1.8/net/protocol.rb:135:in `rbuf_fill' from /usr/lib/ruby/1.8/timeout.rb:62:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:93:in `timeout' from /usr/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill' from /usr/lib/ruby/1.8/net/protocol.rb:116:in `readuntil' from /usr/lib/ruby/1.8/net/protocol.rb:126:in `readline' from /usr/lib/ruby/1.8/net/http.rb:2020:in `read_status_line' from /usr/lib/ruby/1.8/net/http.rb:2009:in `read_new' from /usr/lib/ruby/1.8/net/http.rb:1050:in `request' from /usr/lib/ruby/1.8/open-uri.rb:248:in `open_http' from /usr/lib/ruby/1.8/net/http.rb:543:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/timeout.rb:60:in `rbuf_fill': execution expired (Timeout::Error) from /usr/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill' from /usr/lib/ruby/1.8/net/protocol.rb:116:in `readuntil' from /usr/lib/ruby/1.8/net/protocol.rb:126:in `readline' from /usr/lib/ruby/1.8/net/http.rb:2020:in `read_status_line' from /usr/lib/ruby/1.8/net/http.rb:2009:in `read_new' from /usr/lib/ruby/1.8/net/http.rb:1050:in `request' from /usr/lib/ruby/1.8/open-uri.rb:248:in `open_http' from /usr/lib/ruby/1.8/net/http.rb:543:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/net/protocol.rb:135:in `sysread': end of file reached (EOFError) from /usr/lib/ruby/1.8/net/protocol.rb:135:in `rbuf_fill' from /usr/lib/ruby/1.8/timeout.rb:62:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:93:in `timeout' from /usr/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill' from /usr/lib/ruby/1.8/net/protocol.rb:116:in `readuntil' from /usr/lib/ruby/1.8/net/protocol.rb:126:in `readline' from /usr/lib/ruby/1.8/net/http.rb:2020:in `read_status_line' from /usr/lib/ruby/1.8/net/http.rb:2009:in `read_new' from /usr/lib/ruby/1.8/net/http.rb:1050:in `request' from /usr/lib/ruby/1.8/open-uri.rb:248:in `open_http' from /usr/lib/ruby/1.8/net/http.rb:543:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/net/http.rb:560:in `initialize': No route to host - connect(2) (Errno::EHOSTUNREACH) from /usr/lib/ruby/1.8/net/http.rb:560:in `open' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/timeout.rb:53:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:93:in `timeout' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/net/http.rb:553:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:542:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' /usr/lib/ruby/1.8/net/http.rb:560:in `initialize': getaddrinfo: Temporary failure in name resolution (SocketError) from /usr/lib/ruby/1.8/net/http.rb:560:in `open' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/timeout.rb:53:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:93:in `timeout' from /usr/lib/ruby/1.8/net/http.rb:560:in `connect' from /usr/lib/ruby/1.8/net/http.rb:553:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:542:in `start' from /usr/lib/ruby/1.8/open-uri.rb:242:in `open_http' from /usr/lib/ruby/1.8/open-uri.rb:616:in `buffer_open' from /usr/lib/ruby/1.8/open-uri.rb:164:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:162:in `catch' from /usr/lib/ruby/1.8/open-uri.rb:162:in `open_loop' from /usr/lib/ruby/1.8/open-uri.rb:132:in `open_uri' from /usr/lib/ruby/1.8/open-uri.rb:518:in `open' from /usr/lib/ruby/1.8/open-uri.rb:30:in `open' -- Yusuke ENDOH