Capturing Ctrl-c in ruby
The problem is that when a Ruby program ends, it does so by raising SystemExit. When a control-C comes in, it raises Interrupt. Since both SystemExit and Interrupt derive from Exception, your exception handling is stopping the exit or interrupt in its tracks. Here's the fix:
Wherever you can, change
rescue Exception => e
# ...
end
to
rescue StandardError => e
# ...
end
for those you can't change to StandardError, re-raise the exception:
rescue Exception => e
# ...
raise
end
or, at the very least, re-raise SystemExit and Interrupt
rescue SystemExit, Interrupt
raise
rescue Exception => e
#...
end
Any custom exceptions you have made should derive from StandardError, not Exception.
If you can wrap your whole program you can do something like the following:
trap("SIGINT") { throw :ctrl_c }
catch :ctrl_c do
begin
sleep(10)
rescue Exception
puts "Not printed"
end
end
This basically has CtrlC use catch/throw instead of exception handling, so unless the existing code already has a catch :ctrl_c in it, it should be fine.
Alternatively you can do a trap("SIGINT") { exit! }
. exit!
exits immediately, it does not raise an exception so the code can't accidentally catch it.
I am using ensure
to great effect! This is for things you want to have happen when your stuff ends no matter why it ends.
If you can't wrap your whole application in a begin ... rescue
block (e.g., Thor) you can just trap SIGINT
:
trap "SIGINT" do
puts "Exiting"
exit 130
end
130 is a standard exit code.