class Smith::SelfPipe
Public Class Methods
new(agent)
click to toggle source
# File lib/smith/self_pipe.rb, line 6 def initialize(agent) @agent = agent @signal_handlers = Hash.new { |h,k| h[k] = Array.new } @signal_handler_queue = [] @signal_handler_pipe_reader, @signal_handler_pipe_writer = IO.pipe setup_signal_handlers end
Public Instance Methods
install_signal_handler(signal, position=:end, &blk)
click to toggle source
Adds a signal handler proc to the list of signal_handlers. When a signal is received all signal handlers are called in reverse order.
@param signal [Integer] the signal number. @param position [Symbol] [:first|:last] where on the signal handler stack
to put the handler proc.
@see Signal.list for a full list of available signals on a system.
# File lib/smith/self_pipe.rb, line 24 def install_signal_handler(signal, position=:end, &blk) raise ArgumentError, "Unknown position: #{position}" if ![:beginning, :end].include?(position) logger.debug { "Installing signal handler for #{signal}" } @signal_handlers[signal].insert((position == :beginning) ? 0 : -1, blk) Signal.trap(signal) { @signal_handler_pipe_writer.write_nonblock('.') @signal_handler_queue << signal } end
setup_signal_handlers()
click to toggle source
Set up the mechanics required to implement the self pipe trick.
# File lib/smith/self_pipe.rb, line 37 def setup_signal_handlers # The Module declaration here will only close over local variables so we # need to assign self to a local variable to get access to the agent itself. clazz = self EM.attach(@signal_handler_pipe_reader, Module.new { define_method :receive_data do |_| handlers = clazz.instance_variable_get(:@signal_handlers) queue = clazz.instance_variable_get(:@signal_handler_queue) signal = queue.pop clazz.send(:logger).debug { "Running signal handlers for: #{signal}" } handlers[signal].each { |handler| handler.call(signal) } end }) end