Class: Preforker::SignalProcessor
- Inherits:
-
Object
- Object
- Preforker::SignalProcessor
- Defined in:
- lib/preforker/signal_processor.rb
Instance Attribute Summary collapse
-
#interesting_signals ⇒ Object
readonly
Returns the value of attribute interesting_signals.
-
#signal_queue ⇒ Object
readonly
Returns the value of attribute signal_queue.
Instance Method Summary collapse
-
#initialize(master) ⇒ SignalProcessor
constructor
A new instance of SignalProcessor.
- #reset ⇒ Object
-
#sleep_master ⇒ Object
wait for a signal hander to wake us up and then consume the pipe Wake up every second anyways to run murder_lazy_workers.
- #start_signal_loop ⇒ Object
- #trap_deferred(signal) ⇒ Object
- #wake_up_master ⇒ Object
Constructor Details
#initialize(master) ⇒ SignalProcessor
Returns a new instance of SignalProcessor.
4 5 6 7 8 9 10 |
# File 'lib/preforker/signal_processor.rb', line 4 def initialize(master) @read_pipe, @write_pipe = IO.pipe @master = master @signal_queue = [] @interesting_signals = [:WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP, :TTIN, :TTOU] @interesting_signals.each { |sig| trap_deferred(sig) } end |
Instance Attribute Details
#interesting_signals ⇒ Object (readonly)
Returns the value of attribute interesting_signals.
3 4 5 |
# File 'lib/preforker/signal_processor.rb', line 3 def interesting_signals @interesting_signals end |
#signal_queue ⇒ Object (readonly)
Returns the value of attribute signal_queue.
3 4 5 |
# File 'lib/preforker/signal_processor.rb', line 3 def signal_queue @signal_queue end |
Instance Method Details
#reset ⇒ Object
82 83 84 85 |
# File 'lib/preforker/signal_processor.rb', line 82 def reset @interesting_signals.each { |sig| trap(sig, nil) } @signal_queue.clear end |
#sleep_master ⇒ Object
wait for a signal hander to wake us up and then consume the pipe Wake up every second anyways to run murder_lazy_workers
62 63 64 65 66 67 68 69 70 71 |
# File 'lib/preforker/signal_processor.rb', line 62 def sleep_master begin maximum_sleep = @master.timeout > 1 ? 1 : @master.timeout / 2 ready = IO.select([@read_pipe], nil, nil, maximum_sleep) or return ready.first && ready.first.first or return chunk_size = 16 * 1024 loop { @read_pipe.read_nonblock(chunk_size) } rescue Errno::EAGAIN, Errno::EINTR end end |
#start_signal_loop ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/preforker/signal_processor.rb', line 23 def start_signal_loop last_check = Time.now begin loop do @master.reap_all_workers case @signal_queue.shift when nil # avoid murdering workers after our master process (or the # machine) comes out of suspend/hibernation @master.murder_lazy_workers if (last_check + @master.timeout) >= (last_check = Time.now) @master.maintain_worker_count sleep_master when :WINCH @master.logger.info "Gracefully stopping all workers" @master.number_of_workers = 0 when :TTIN @master.number_of_workers += 1 when :TTOU @master.number_of_workers -= 1 if @master.number_of_workers > 0 when :QUIT # graceful shutdown break when :TERM, :INT # immediate shutdown @master.stop(false) break end end rescue Errno::EINTR retry rescue => e @master.logger.error "Unhandled master loop exception #{e.inspect}.\n#{e.backtrace.join("\n")}" retry ensure @master.logger.info "Master quitting" @master.quit end end |
#trap_deferred(signal) ⇒ Object
12 13 14 15 16 17 18 19 20 21 |
# File 'lib/preforker/signal_processor.rb', line 12 def trap_deferred(signal) trap(signal) do if @signal_queue.size < 5 @signal_queue << signal wake_up_master else @master.logger.error "ignoring SIG#{signal}, queue=#{@signal_queue.inspect}" end end end |
#wake_up_master ⇒ Object
73 74 75 76 77 78 79 80 |
# File 'lib/preforker/signal_processor.rb', line 73 def wake_up_master begin @write_pipe.write_nonblock('.') # wakeup master process from select rescue Errno::EAGAIN, Errno::EINTR # pipe is full, master should wake up anyways retry end end |