Capturando Ctrl-c en ruby

Me pasaron un progtwig de Ruby heredado de larga duración, que tiene numerosas apariciones de

begin #dosomething rescue Exception => e #halt the exception's progress end 

a lo largo de ello.

Sin rastrear todas las excepciones posibles que estos podrían estar manejando (al menos no de inmediato), todavía me gustaría poder apagarlo a veces con Ctrl C.

Y me gustaría hacerlo de una manera que solo se agregue al código (de modo que no afecte el comportamiento existente, o me pierda una excepción capturada de otra manera en medio de una ejecución).

[ 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 surge este problema.]

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 correcta. Eso es SystemExit, Interrupt o IRB :: Abort como se muestra a continuación.

El problema es que cuando un progtwig de Ruby finaliza, lo hace elevando SystemExit . Cuando entra un control-C, provoca Interrupción . Dado que tanto SystemExit como Interrupt derivan de Exception , su manejo de excepciones es detener 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 elevar la excepción:

 rescue Exception => e # ... raise end 

o, al menos, volver a elevar SystemExit e Interrumpir

 rescue SystemExit, Interrupt raise rescue Exception => e #... end 

Cualquier excepción personalizada que haya hecho debe derivarse de StandardError , no de Exception .

Si puedes envolver todo tu progtwig, puedes 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 hace que Ctrl C use catch / throw en lugar de un manejo de excepciones, por lo tanto, a menos que el código existente ya tenga un catch: ctrl_c, debería estar bien.

Alternativamente, puede hacer una trap("SIGINT") { exit! } trap("SIGINT") { exit! } . exit! sale inmediatamente, no genera una excepción, por lo que el código no puede atraparla accidentalmente.

Si no puede envolver toda su aplicación en un bloque de begin ... rescue (por ejemplo, Thor), puede simplemente interceptar SIGINT :

 trap "SIGINT" do puts "Exiting" exit 130 end 

130 es un código de salida estándar.

Estoy utilizando ensure a gran efecto! Esto es para cosas que quieres que sucedan cuando tus cosas terminan, sin importar por qué terminen.

Intereting Posts