[ACCEPTED]-Capturing Ctrl-c in ruby-copy-paste
The problem is that when a Ruby program 9 ends, it does so by raising SystemExit. When a control-C 8 comes in, it raises Interrupt. Since both SystemExit and Interrupt derive 7 from Exception, your exception handling is stopping 6 the exit or interrupt in its tracks. Here's 5 the fix:
Wherever you can, change
rescue Exception => e
# ...
end
to
rescue StandardError => e
# ...
end
for those 4 you can't change to StandardError, re-raise 3 the exception:
rescue Exception => e
# ...
raise
end
or, at the very least, re-raise 2 SystemExit and Interrupt
rescue SystemExit, Interrupt
raise
rescue Exception => e
#...
end
Any custom exceptions 1 you have made should derive from StandardError, not Exception.
If you can wrap your whole program you can 7 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 6 has CtrlC use catch/throw instead of exception 5 handling, so unless the existing code already 4 has a catch :ctrl_c in it, it should be 3 fine.
Alternatively you can do a trap("SIGINT") { exit! }
. exit!
exits 2 immediately, it does not raise an exception 1 so the code can't accidentally catch it.
If you can't wrap your whole application 2 in a begin ... rescue
block (e.g., Thor) you can just trap 1 SIGINT
:
trap "SIGINT" do
puts "Exiting"
exit 130
end
130 is a standard exit code.
I am using ensure
to great effect! This is for 2 things you want to have happen when your 1 stuff ends no matter why it ends.
Handling Ctrl-C cleanly in Ruby the ZeroMQ way:
#!/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
0
Perhaps the most simple solution?
Signal.trap('INT') { exit }
This is 5 what I use, it works. Put it somewhere before a 4 possible user interaction.
Here, a more verbose 3 solution, to print something to STDERR and 2 exit:
Signal.trap('INT') { abort 'Interrupted by user' }
See here for difference between exit and 1 abort.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.