Class: Trident::SignalHandler

Inherits:
Object
  • Object
show all
Includes:
GemLogger::LoggerSupport
Defined in:
lib/trident/signal_handler.rb

Constant Summary collapse

CHUNK_SIZE =
(16 * 1024)
SIGNAL_QUEUE_MAX_SIZE =
5
MSG_STOP =
'STOP'

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(signal_mappings, target) ⇒ SignalHandler

Returns a new instance of SignalHandler.



37
38
39
40
41
42
43
# File 'lib/trident/signal_handler.rb', line 37

def initialize(signal_mappings, target)
  @target = target
  @signal_queue = []
  @self_pipe = []
  @original_signal_handlers = {}
  self.signal_mappings = signal_mappings
end

Class Attribute Details

.instanceObject

Returns the value of attribute instance.



11
12
13
# File 'lib/trident/signal_handler.rb', line 11

def instance
  @instance
end

Instance Attribute Details

#original_signal_handlersObject (readonly)

Returns the value of attribute original_signal_handlers.



35
36
37
# File 'lib/trident/signal_handler.rb', line 35

def original_signal_handlers
  @original_signal_handlers
end

#self_pipeObject (readonly)

Returns the value of attribute self_pipe.



35
36
37
# File 'lib/trident/signal_handler.rb', line 35

def self_pipe
  @self_pipe
end

#signal_mappingsObject

Returns the value of attribute signal_mappings.



35
36
37
# File 'lib/trident/signal_handler.rb', line 35

def signal_mappings
  @signal_mappings
end

#signal_queueObject (readonly)

Returns the value of attribute signal_queue.



35
36
37
# File 'lib/trident/signal_handler.rb', line 35

def signal_queue
  @signal_queue
end

#targetObject (readonly)

Returns the value of attribute target.



35
36
37
# File 'lib/trident/signal_handler.rb', line 35

def target
  @target
end

Class Method Details

.reset_for_forkObject



27
28
29
30
31
# File 'lib/trident/signal_handler.rb', line 27

def reset_for_fork
  raise "No signal handler started" unless instance
  instance.reset_for_fork
  self.instance = nil
end

.start(signal_mappings, target) ⇒ Object



13
14
15
16
17
18
# File 'lib/trident/signal_handler.rb', line 13

def start(signal_mappings, target)
  raise "Already started, call stop if restart needed" if instance
  logger.info "Starting signal handler"
  self.instance = new(signal_mappings, target)
  instance.start
end

.stopObject



20
21
22
23
24
25
# File 'lib/trident/signal_handler.rb', line 20

def stop
  raise "No signal handler started" unless instance
  logger.info "Stopping signal handler"
  instance.stop
  self.instance = nil
end

Instance Method Details

#reset_for_forkObject



66
67
68
69
# File 'lib/trident/signal_handler.rb', line 66

def reset_for_fork
  @self_pipe = []
  reset_signal_handlers
end

#snoozeObject



82
83
84
85
86
87
88
89
90
91
# File 'lib/trident/signal_handler.rb', line 82

def snooze
  msg = ""
  begin
    ready = IO.select([self_pipe.first], nil, nil, 1) or return
    ready.first && ready.first.first or return
    loop { msg << self_pipe.first.read_nonblock(CHUNK_SIZE) }
  rescue Errno::EAGAIN, Errno::EINTR
  end
  msg
end

#startObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/trident/signal_handler.rb', line 45

def start
  setup_self_pipe
  setup_signal_handlers

  logger.info "Main loop started"
  loop do
    signal_result = handle_signal_queue
    break if signal_result == :break
    logger.debug "Snoozing main loop"
    msg = snooze if signal_queue.empty?
    logger.debug "Main loop awakened: #{msg.inspect}"
    break if msg == MSG_STOP
  end
  logger.info "Main loop exited"
end

#stopObject



61
62
63
64
# File 'lib/trident/signal_handler.rb', line 61

def stop
  reset_signal_handlers
  wakeup(MSG_STOP)
end

#wakeup(msg = '.') ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/trident/signal_handler.rb', line 71

def wakeup(msg='.')
  begin
    # mutexes (and thus logging) not allowed within a trap context
    # puts "Waking main loop"
    self_pipe.last.write_nonblock(msg) # wakeup master process from select
  rescue Errno::EAGAIN, Errno::EINTR
    # pipe is full, master should wake up anyways
    retry
  end
end