ruby/ruby — pull request #597 by pranas (2014-04-15 15:32:19+00:00)
Title: Use Ruby DNS resolver to handle DNS timeout

This is a patch for Net::HTTP standard library.

I ran into an issue when DNS resolution failed because of poor network connection. In this case, even though I had Net::HTTP open_timeout set it didn't stop the operation but kept hanging until some low level timeout (30s) stopped it. I was seeing error messages like this:

````
getaddrinfo: nodename nor servname provided, or not known for host ******:80
````

I traced it to ``lib/net/http.rb:880`` where it calls ``TCPSocket.open`` within ``Timeout.timeout`` block. I dived into the C code for TCPSocket and eventually found a syscall to ``getaddrinfo``. This is a blocking syscall which cannot be handled by Ruby timeout mechanism.

I'm not sure why this issue hasn't been reported before. I think ``open_timeout`` should halt the execution no matter if there is an issue with DNS or opening network connection to the host.

I looked for people experiencing similar issues and found [this thread](https://www.ruby-forum.com/topic/195798). I took the idea for my patch from there. This small patch calls Ruby DNS resolver first before passing connection address to TCPSocket. Ruby DNS resolver works nice with timeouts.

As far as I can see it shouldn't introduce any problems or significant performance degradation. Please review and give your feedback.

For everybody else experiencing this issue as a workaround I suggest to use ``Resolv.getaddress(hostname)`` inside ``Timeout.timeout`` block before passing connection address to Net::HTTP. If this patch gets accepted it will make Net::HTTP open_timeout more reliable for everyone.