class Sigurd::SignalHandler
Class that takes any object with a “start” and “stop” method and catches signals to ask them to stop nicely.
Constants
- SIGNALS
Attributes
reader[R]
runner[R]
signal_queue[R]
writer[R]
Public Class Methods
new(runner)
click to toggle source
Takes any object that responds to the `start` and `stop` methods. @param runner[#start, stop]
# File lib/sigurd/signal_handler.rb, line 12 def initialize(runner) @signal_queue = [] @reader, @writer = IO.pipe @runner = runner end
Public Instance Methods
run!()
click to toggle source
Run the runner.
# File lib/sigurd/signal_handler.rb, line 19 def run! setup_signals @runner.start loop do case signal_queue.pop when *SIGNALS @runner.stop break else ready = IO.select([reader, writer]) # drain the self-pipe so it won't be returned again next time reader.read_nonblock(1) if ready[0].include?(reader) end end end
Private Instance Methods
prepend_handler(signal) { || ... }
click to toggle source
stackoverflow.com/questions/29568298/run-code-when-signal-is-sent-but-do-not-trap-the-signal-in-ruby
# File lib/sigurd/signal_handler.rb, line 42 def prepend_handler(signal) previous = Signal.trap(signal) do previous = -> { raise SignalException, signal } unless previous.respond_to?(:call) yield previous.call end end
setup_signals()
click to toggle source
Trap signals using the self-pipe trick.
# File lib/sigurd/signal_handler.rb, line 51 def setup_signals at_exit { @runner&.stop } SIGNALS.each do |signal| prepend_handler(signal) do unblock(signal) end end end
unblock(signal)
click to toggle source
Save the signal to the queue and continue on. @param signal [Symbol]
# File lib/sigurd/signal_handler.rb, line 62 def unblock(signal) writer.write_nonblock('.') signal_queue << signal end