Ruby rant: Timeout::Error

Jan 24, 2008 17:44

I am currently filled with hate and loathing. I'm going to need a few moments to cool off before I carry on working.

I was trying to make an http call from an irb session full of state I had carefully collected. Most of the code I used is in a script, but I had been doing a substantial amount of exploration over data from a few different place. While waiting for a large dataset from a busy server on the other end of a high-latency link, I got a timeout in the HTTP receive stuff. This in itself would not be a problem, except it crashed my irb session.

The problem is with the exception that a timeout raises:

module Timeout
class Error < Interrupt
end
end
The initiated will know that (a subset of) the Ruby exception hierarchy looks something like this:

Exception
- StandardError
- RuntimeError
- ZeroDivisionError
- ScriptError
- SyntaxError
- SystemExit
- SignalException
- Interrupt
The important bit there is that all the stuff you can reasonably expect to recover from is under StandardError. Because of this, a default rescue block will not catch anything that isn't a StandardError. The observant reader will notice that I helpfully showed Interrupt's position in the hierarchy. The observant reader will also notice that it is not a subclass of StandardError. This means that you need to catch it explicitly, or it will cause a crash.

Now, my theory is that Timeout was written by someone who misinterpreted "Interrupt" as meaning "interrupt what I'm doing", not "interrupt my application". This would be understandable, although still not acceptable, in a third-party library. Timeout is a core standard library module, however.

To summarise: If you're using the standard Ruby timeout mechanism, which you are if you use the HTTP libraries and almost certainly a whole host of others, you need to explicitly catch Timeout::Error or have a dodgy network bring your entire application crashing down around you.

programming, ruby, rant

Previous post Next post
Up