Timeout::Error - catchable?

Hi,

I’m having trouble catching the exception raised by Timeout.timeout

Using the following code:

require ‘timeout’
begin
Timeout::timeout(1) do
sleep(5)
end
rescue
puts “rescued in outer”
end

The interpreter stops with the following:

/usr/lib/ruby/1.8/timeout.rb:54: execution expired (Timeout::Error)
from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout’
from test.rb:21

I can’t catch the exception from within the block, either:

require ‘timeout’
Timeout::timeout(1) do
begin
sleep(5)
rescue
puts “rescued in inner”
end
end

This gives the same error:

/usr/lib/ruby/1.8/timeout.rb:54: execution expired (Timeout::Error)
from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout’
from test2.rb:8

Is this a known problem, or am I using Timeout incorrectly?

I am using a workaround for now – my own implementation:

module TimeLimit

class Expired < RuntimeError; end

def self.timeout(sec, &block)
worker = Thread.new(&block)
killer = Thread.new { sleep sec; worker.raise Expired.new if
worker.alive? }
worker.join
killer.kill if killer.alive?
end

end

With the above code, the following prints ‘expired’ followed by
‘finished’, as I would expect:

TimeLimit::timeout(1) do
begin
sleep 5
puts “finished”
rescue TimeLimit::Expired
puts “expired”
end
end

TimeLimit::timeout(5) do
begin
sleep 1
puts “finished”
rescue TimeLimit::Expired
puts “expired”
end
end

Cheers,
Rik

Le 13 août à 15:48, Rik Hemsley a écrit :

The interpreter stops with the following:

/usr/lib/ruby/1.8/timeout.rb:54: execution expired (Timeout::Error)
from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout’
from test.rb:21

Why don’t you simply rescue Timeout::Error ?

Timeout::timeout(1) do
begin
sleep(5)
rescue Timeout::Error
puts “rescued”
end
end

Fred

You should handle the exception clearly, that is, rescue TimeoutError.

The default action of rescue is to catch the exception which is a
subclass
of StandardError, but unfortunately, TimeoutError is not.

Le 13 août à 14:08, Rik Hemsley a écrit :

I thought ‘rescue’ was a catch-all. Obviously not. Thanks!

Rescue catches everything under StandardError. If you really want a
catch-all, you need to “rescue Exception” explicitly.

Fred

On 8/13/07, F. Senault [email protected] wrote:

puts "rescued"

end
end

I thought ‘rescue’ was a catch-all. Obviously not. Thanks!

Rescue catches everything under StandardError. If you really want a
catch-all, you need to “rescue Exception” explicitly.

And don’t do that, there are likely things you actually don’t want to
catch.

Fred

On Aug 13, 3:04 pm, “F. Senault” [email protected] wrote:

Why don’t you simply rescue Timeout::Error ?

Timeout::timeout(1) do
begin
sleep(5)
rescue Timeout::Error
puts “rescued”
end
end

I thought ‘rescue’ was a catch-all. Obviously not. Thanks!

Rik

On Aug 13, 2007, at 07:04, F. Senault wrote:

Timeout::timeout(1) do
begin
sleep(5)
rescue Timeout::Error
puts “rescued”
end
end

You really want to subclass Timeout::Error and rescue that. If other
code calls yours with a timeout you have the potential for rescuing
the outer one rather than the one you want.

See: http://blog.segment7.net/articles/2006/04/11/care-and-feeding-of-
timeout-timeout