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

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

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

Fred

···

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

--
You make this all go away (2x) I'm down to just one thing I'm starting
to scare myself You make this all go away (2x) I just want something
I just want something I can never have
                           (Nine Inch Nails, Something I Can Never Have)

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.

···

On 8/13/07, Rik Hemsley <rikkus@gmail.com> wrote:

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

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

Rik

···

On Aug 13, 3:04 pm, "F. Senault" <f...@lacave.net> wrote:

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

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

···

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

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

--
Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars

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

Fred

···

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

On Aug 13, 3:04 pm, "F. Senault" <f...@lacave.net> 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!

--
It's obvious that as well as my previous idea for phones with caller-IQ,
we now also need to have a CallerSPECmark feature to deal with automated
dialers - something that issues the automated-dialer-equivalent of "550:
get stuffed - you have the CPU-power of a footstool". (Tanuki, SDM)

>> 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!

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 8/13/07, F. Senault <fred@lacave.net> wrote:

Le 13 août à 14:08, Rik Hemsley a écrit :
> On Aug 13, 3:04 pm, "F. Senault" <f...@lacave.net> wrote:
--
It's obvious that as well as my previous idea for phones with caller-IQ,
we now also need to have a CallerSPECmark feature to deal with automated
dialers - something that issues the automated-dialer-equivalent of "550:
get stuffed - you have the CPU-power of a footstool". (Tanuki, SDM)