¿Es SystemExit un tipo especial de excepción?

¿Cómo se comporta SystemExit manera diferente de otras Exception ? Creo que entiendo algunos de los razonamientos acerca de por qué no sería bueno plantear una Excepción adecuada. Por ejemplo, no querrías que sucediera algo extraño como esto:

 begin exit rescue => e # Silently swallow up the exception and don't exit end 

Pero, ¿cómo ignora el rescue SystemExit ? (¿Qué criterios utiliza?)

Cuando escribes rescue sin una o más clases, es lo mismo que escribir:

 begin ... rescue StandardError => e ... end 

Sin embargo, hay excepciones que no se heredan de StandardError . SystemExit es uno de estos, y por lo tanto no se captura. Aquí hay un subconjunto de la jerarquía en Ruby 1.9.2, que puede descubrir usted mismo :

 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 

Por lo tanto, puede capturar solo SystemExit con:

 begin ... rescue SystemExit => e ... end 

… o puede elegir capturar todas las excepciones, incluido SystemExit con:

 begin ... rescue Exception => e ... end 

Inténtalo tú mismo:

 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..." 

Tenga en cuenta que este ejemplo no funcionará en (¿algunas versiones de?) IRB, que proporciona su propio método de salida que enmascara la salida normal de Object #.

En 1.8.7:

 method :exit #=> # 

En 1.9.3:

 method :exit #=> # 

Ejemplo simple:

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

El status salida / success? , etc. se puede leer también:

 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 

Lista completa de métodos: [:status, :success?, :exception, :message, :backtrace, :backtrace_locations, :set_backtrace, :cause]