Sy Ali wrote:
Just for kicks I tried to better understand what’s going on with trap.
Maybe I misunderstand what it’s for, but it doesn’t seem to work the
way I want. I can’t seem to properly trap based on the signal name,
and reading through some docs led me to this type of code:
Signals are used to asynchronously interrupt programs. For example when
you press Ctrl+C, the operating system sends SIGINT (the “interrupt”
signal) to whatever program’s running.
You can send signals programmatically, in Ruby using
Process.kill(signal, process_id), and you set signal-handlers to deal
with signals your program is sent using trap.
In the case of SIGINT, Ruby would normally raise the exception Interrupt
(a subclass of SignalException). As with any exception, if that’s not
handled, the program will terminate.
So we specify alternate behaviour with trap.
trap :INT, begin
require ‘termios’ # http://raa.ruby-lang.org/project/ruby-termios/
c = Termios.tcgetattr(STDIN).cc[Termios::VINTR]
proc { STDIN << c }
rescue LoadError
proc {}
end
The overall format is trap(:INT, …) – the return value of the
begin…end block is being passed as the handler for trap.
The simple case is just “trap(:INT, proc {}”. That means, “if I get a
SIGINT, do nothing.”
The termios stuff is only going to work on *nix and if the ruby-termios
package is installed. It gets the character that the terminal converts
into a SIGINT, and puts in on the input stream. (Because *nixes
apparently don’t send the character if it’s the SIGINT character;
Windows does.)
Either way, the main point is simply to avoid Ctrl+C crashing the
program.
but I don’t know the correct signal to use.
0 is SIGEXIT. You’ll get a SIGEXIT as your program terminates:
C:>ruby
trap(:EXIT, proc {puts “bye”})
^Z
bye
C:>
I’m tipping all you care about is SIGINT.
Now I’m going to give up, not just because it’s almost 3am but because
catching 3 from read_char does the job for me. If/when I end up
working with signals I’ll definitely need to revisit this stuff.
Interesting… it appears no trap’s necessary on Windows if you’re using
_getch. You can use ?\cC instead of 3.
puts “This shouldn’t display upon interrupt.”
puts " … but it always displays"
Signal.trap(3, lambda { puts “interrupted…” ; exit })
Your trap isn’t being added until it’s too late. While you’re in
read_char, Windows’ _getch function will return 3 rather than be
interrupted, so that works fine anyway.
Cheers,
Dave