私は長い間実行されているレガシーRubyプログラムに合格しました。
_begin
#dosomething
rescue Exception => e
#halt the exception's progress
end
_
それ全体。
すべての可能な例外を追跡せずに、これらのそれぞれが処理している可能性があります(少なくともすぐにではありません)。 CtrlC。
そして、コードに追加するだけの方法でこれを行いたいです(したがって、既存の動作に影響を与えたり、実行中にキャッチされた例外を逃したりしません)。
[CtrlC SIGINT、またはSystemExitは、Rubyの例外処理システムのSignalException.new("INT")
と同等のようです。 _class SignalException < Exception
_。このため、この問題が発生します。]
私が書きたいコードは次のとおりです。
_begin
#dosomething
rescue SignalException => e
raise e
rescue Exception => e
#halt the exception's progress
end
_
編集:このコードは、トラップしたい例外のクラスを取得する限り機能します。これは、SystemExit、Interrupt、またはIRB :: Abortのいずれかです
問題は、Rubyプログラムが終了するとき、SystemExitを上げることによってそうすることです。control-Cが入ってくると、Interruptを上げます。 =。SystemExitとInterruptの両方がExceptionから派生しているため、例外処理はそのトラックで出口または割り込みを停止しています。
どこでもできる
rescue Exception => e
# ...
end
に
rescue StandardError => e
# ...
end
standardErrorに変更できない場合は、例外を再度発生させます。
rescue Exception => e
# ...
raise
end
または、少なくともSystemExitと割り込みを再発生させます
rescue SystemExit, Interrupt
raise
rescue Exception => e
#...
end
作成したカスタム例外は、ExceptionではなくStandardErrorから派生する必要があります。
プログラム全体をラップできる場合は、次のようなことができます。
_ trap("SIGINT") { throw :ctrl_c }
catch :ctrl_c do
begin
sleep(10)
rescue Exception
puts "Not printed"
end
end
_
これは基本的に CtrlC 例外処理の代わりにcatch/throwを使用してください。したがって、既存のコードに既にcatch:ctrl_cが含まれていない限り、問題ありません。
または、trap("SIGINT") { exit! }
を実行できます。 _exit!
_はすぐに終了しますが、例外を発生させないため、コードが誤ってキャッチすることはありません。
アプリケーション全体をbegin ... rescue
ブロック(たとえば、Thor)でラップできない場合は、SIGINT
をトラップできます。
trap "SIGINT" do
puts "Exiting"
exit 130
end
130は標準の終了コードです。
私はensure
を非常に効果的に使用しています!これは、何が終了したとしても、あなたのスタッフが終了したときに起こりたいことのためです。
RubyでCtrl-Cをきれいに処理するZeroMQの方法:
#!/usr/bin/env Ruby
# Shows how to handle Ctrl-C
require 'ffi-rzmq'
context = ZMQ::Context.new(1)
socket = context.socket(ZMQ::REP)
socket.bind("tcp://*:5558")
trap("INT") { puts "Shutting down."; socket.close; context.terminate; exit}
puts "Starting up"
while true do
message = socket.recv_string
puts "Message: #{message.inspect}"
socket.send_string("Message received")
end