How does SystemExit behave differently from other Exceptions? I think I understand some of the reasoning about why it wouldn't be good to raise a proper Exception. For example, you wouldn't want something strange like this to happen:
begin
exit
rescue => e
# Silently swallow up the exception and don't exit
end
But how does the rescue ignore SystemExit? (What criteria does it use?)
解决方案
When you write rescue without one or more classes, it is the same as writing:
begin
...
rescue StandardError => e
...
end
There are Exceptions that do not inherit from StandardError, however. SystemExit is one of these, and so it is not captured. Here is a subset of the hierarchy in Ruby 1.9.2, which you can find out yourself:
BasicObject
Exception
NoMemoryError
ScriptError
LoadError
Gem::LoadError
NotImplementedError
SyntaxError
SecurityError
SignalException
Interrupt
StandardError
ArgumentError
EncodingError
Encoding::CompatibilityError
Encoding::ConverterNotFoundError
Encoding::InvalidByteSequenceError
Encoding::UndefinedConversionError
FiberError
IOError
EOFError
IndexError
KeyError
StopIteration
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SystemCallError
ThreadError
TypeError
ZeroDivisionError
SystemExit
SystemStackError
fatal
You can thus capture just SystemExit with:
begin
...
rescue SystemExit => e
...
end
...or you can choose to capture every exception, including SystemExit with:
begin
...
rescue Exception => e
...
end
Try it yourself:
begin
exit 42
puts "No no no!"
rescue Exception => e
puts "Nice try, buddy."
end
puts "And on we run..."
#=> "Nice try, buddy."
#=> "And on we run..."
Note that this example will not work in (some versions of?) IRB, which supplies its own exit method that masks the normal Object#exit.
In 1.8.7:
method :exit
#=> #
In 1.9.3:
method :exit
#=> #