开发者

Is SystemExit a special kind of Exception?

How does SystemExit behave differently from other Exceptions? I think I understand some of the reasoning about why it wouldn't be go开发者_运维知识库od 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
#=> #<Method: Object(IRB::ExtendCommandBundle)#exit>

In 1.9.3:

method :exit
#=> #<Method: main.irb_exit>


Simple example:

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exception"
end

puts "after begin block"

The exit status / success?, etc. can be read too:

begin
  exit 1
rescue SystemExit => e
  puts "Success? #{e.success?}" # Success? false
end

begin
  exit
rescue SystemExit => e
  puts "Success? #{e.success?}" # Success? true
end

Full list of methods: [:status, :success?, :exception, :message, :backtrace, :backtrace_locations, :set_backtrace, :cause]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜