How to rescue any exception in 1.8?

P

Philip Mak

This code will catch the exception in Ruby 1.6:

require 'timeout'
begin
raise TimeoutError
rescue
puts "Rescued!"
end

But in Ruby 1.8, it will not catch the exception. I found out that if
I do "rescue Exception" instead of just "rescue", it will work.

So, my question is, if I want to rescue any exception no matter what
it is, do I have to start typing "rescue Exception" instead of
"rescue"?
 
K

Kent Dahl

Philip said:
This code will catch the exception in Ruby 1.6:

require 'timeout'
begin
raise TimeoutError
rescue
puts "Rescued!"
end

But in Ruby 1.8, it will not catch the exception. I found out that if
I do "rescue Exception" instead of just "rescue", it will work.

So, my question is, if I want to rescue any exception no matter what
it is, do I have to start typing "rescue Exception" instead of
"rescue"?

Yes.

Rescue without an Exception type only catches StandardError and
subclasses. The inheritance hierarchy of exceptions are one of the
changes between 1.6 and 1.8, IIRC...

[kentda@v052a kentda]$ ruby -v -e "require 'timeout';p
TimeoutError.ancestors"
ruby 1.6.8 (2002-12-24) [i386-linux-gnu]
[TimeoutError, StandardError, Exception, Object, Kernel]

[kentda@v052a kentda]$ /usr/local/bin/ruby -v -e "require 'timeout';p
TimeoutError.ancestors"
ruby 1.8.0 (2003-07-24) [i686-linux]
[Timeout::Error, Interrupt, SignalException, Exception, Object, Kernel]

HTH
 
B

Brian Candler

This code will catch the exception in Ruby 1.6:

require 'timeout'
begin
raise TimeoutError
rescue
puts "Rescued!"
end

But in Ruby 1.8, it will not catch the exception. I found out that if
I do "rescue Exception" instead of just "rescue", it will work.

So, my question is, if I want to rescue any exception no matter what
it is, do I have to start typing "rescue Exception" instead of
"rescue"?

In general, you always did:

$ ruby16 -ve 'begin; require "flurble"; rescue; puts "ok"; end'
ruby 1.6.8 (2002-12-24) [i386-freebsd4.8]
-e:1:in `require': No such file to load -- flurble (LoadError)
from -e:1

$ ruby16 -ve 'begin; require "flurble"; rescue Exception; puts "ok"; end'
ruby 1.6.8 (2002-12-24) [i386-freebsd4.8]
ok

'rescue' by itself is like 'rescue StandardError', I believe (which catches
StandardError and all its subclasses)

However it does look like timeout exceptions have changed from 1.6.8 to 1.8

1.6.8: raised TimeoutError, which was a subclass of StandardError
1.8.0: raises Timeout::Error, which is a subclass of Interrupt

However in 1.8.0 you can pass in an exception class, so you can do:

require 'timeout'
begin
timeout(3, StandardError) do
sleep 5
end
rescue
puts "ok"
end

Or, to make your code compatible with both versions, without trapping
absolutely every exception, you can do

rescue StandardError, Interrupt

Cheers,

Brian.
 
B

Brian Candler

Unfortunately the on-line version of the Pickaxe book doesn't have the image
which shows the exception hierarchy. There are probably a zillion programs
for dumping this out, but here's another one anyway:

require 'timeout'

class ObjTree
def initialize
@children = Hash.new([])
ObjectSpace.each_object(Class) do |c|
@children[c.superclass] += [c]
end
end

def dumptree(klass, level = 0)
puts " "*level + "" + klass.to_s
@children[klass].sort {|x,y| x.to_s<=>y.to_s}.each do |c|
dumptree(c, level+1)
end
end
end

ObjTree.new.dumptree(Exception) # or try Object
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top