rails - Capturando Ctrl-c en ruby
rescue in ruby (4)
El problema es que cuando termina un programa Ruby, lo hace al aumentar SystemExit . Cuando entra un control-C, aumenta la interrupción . Dado que tanto SystemExit como Interrupt derivan de Exception , el manejo de su excepción detiene la salida o la interrupción en sus pistas. Aquí está la solución:
Donde sea que puedas, cambia
rescue Exception => e
# ...
end
a
rescue StandardError => e
# ...
end
para aquellos que no puede cambiar a StandardError, vuelva a plantear la excepción:
rescue Exception => e
# ...
raise
end
o, como mínimo, vuelva a subir SystemExit e Interrupt
rescue SystemExit, Interrupt
raise
rescue Exception => e
#...
end
Cualquier excepción personalizada que haya realizado debe derivar de StandardError , no de Exception .
Me aprobaron un programa de ruby heredado de larga ejecución, que tiene numerosas apariciones de
begin
#dosomething
rescue Exception => e
#halt the exception''s progress
end
a lo largo de todo.
Sin rastrear cada una de las posibles excepciones que cada una de ellas podría estar manejando (al menos no de forma inmediata), aún me gustaría poder cerrarla a veces con Ctrl C.
Y me gustaría hacerlo de una manera que solo agregue al código (para no afectar el comportamiento existente, o perder una excepción atrapada en el medio de una carrera).
[ Ctrl C es SIGINT, o SystemExit, que parece ser equivalente a SignalException.new("INT")
en el sistema de manejo de excepciones de Ruby. class SignalException < Exception
, por lo que este problema aparece.]
El código que me gustaría haber escrito sería:
begin
#dosomething
rescue SignalException => e
raise e
rescue Exception => e
#halt the exception''s progress
end
EDITAR: Este código funciona, siempre y cuando obtenga la clase de la excepción que desea capturar correctamente. Eso es SystemExit, Interrupt o IRB :: Abort como se muestra a continuación.
Estoy usando ensure
para un gran efecto! Esto es para las cosas que quieres que sucedan cuando tus cosas terminan sin importar por qué termina.
Si no puede envolver toda su aplicación en un bloque de begin ... rescue
(por ejemplo, Thor), puede atrapar SIGINT
:
trap "SIGINT" do
puts "Exiting"
exit 130
end
130 es un código de salida estándar.
Si puede ajustar todo su programa, puede hacer algo como lo siguiente:
trap("SIGINT") { throw :ctrl_c }
catch :ctrl_c do
begin
sleep(10)
rescue Exception
puts "Not printed"
end
end
Básicamente, esto tiene Ctrl C usar catch / throw en lugar de manejo de excepciones, así que a menos que el código existente ya tenga un catch: ctrl_c en él, debería estar bien.
Alternativamente, puedes hacer una trap("SIGINT") { exit! }
trap("SIGINT") { exit! }
. exit!
sale inmediatamente, no genera una excepción por lo que el código no puede atraparlo accidentalmente.