Class: MainLoop::Loop

Inherits:
Object
  • Object
show all
Defined in:
lib/main_loop/loop.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bus, dispatcher, logger: nil) ⇒ Loop

Returns a new instance of Loop.



12
13
14
15
16
17
18
# File 'lib/main_loop/loop.rb', line 12

def initialize(bus, dispatcher, logger: nil)
  STDOUT.sync = true
  STDERR.sync = true
  @bus = bus
  @dispatcher = dispatcher
  @logger = logger || Logger.new(nil)
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



10
11
12
# File 'lib/main_loop/loop.rb', line 10

def logger
  @logger
end

Instance Method Details

#crash(_command) ⇒ Object



88
89
90
# File 'lib/main_loop/loop.rb', line 88

def crash(_command)
  @dispatcher.crash
end

#install_signal_handlers(bus) ⇒ Object

:nocov:



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/main_loop/loop.rb', line 58

def install_signal_handlers(bus)
  TERM_SIGNALS.each do |sig|
    trap(sig) do |*_args|
      Thread.new(bus) {|b| b.puts "sig:#{sig}" }
    end
  end

  trap 'CLD' do
    Thread.new(bus) {|b| b.puts 'sig:CLD' }
  end
end

#reap(command) ⇒ Object



92
93
94
95
# File 'lib/main_loop/loop.rb', line 92

def reap(command)
  _, id, status = command.split(':')
  @dispatcher.reap_by_id(id, status)
end

#reap_childrenObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/main_loop/loop.rb', line 97

def reap_children
  results = []

  @dispatcher.pids.each do |pid|
    if (result = self.wait2(pid))
      results << result
    end
  end

  Timeouter.loop(2) do
    unless (result = self.wait2(-1))
      break
    end

    results << result
  end

  results
rescue Errno::ECHILD
  results
end

#run(timeout = 0) ⇒ Object



20
21
22
23
24
25
26
27
28
29
# File 'lib/main_loop/loop.rb', line 20

def run(timeout = 0)
  install_signal_handlers(@bus)

  start_loop_forever(timeout)
rescue StandardError => e
  # :nocov:
  logger.fatal("Exception in Main Loop: #{e.inspect}")
  exit!(2)
  # :nocov:
end

#signal(command) ⇒ Object

:nocov:



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/main_loop/loop.rb', line 71

def signal(command)
  _, sig = command.split(':')
  logger.debug("signal:#{sig}")

  if TERM_SIGNALS.include?(sig)
    @dispatcher.term
  elsif sig == 'CLD'
    # nothing to do child will reap later
  else
    logger.info("unhandled signal:#{sig}")
  end
end

#start_loop_forever(timeout = 0) ⇒ Object



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
# File 'lib/main_loop/loop.rb', line 31

def start_loop_forever(timeout = 0)
  wait = [[(timeout / 2.5), 5].min, 5].max
  Timeouter.loop(timeout) do
    event = @bus.gets(wait)
    logger.debug("command:#{event}")

    case event
    when 'term'
      term(event)
    when 'crash'
      crash(event)
    when /sig:/
      signal(event)
    when /reap:/
      reap(event)
    when nil
      logger.debug('Empty event: reaping...')
    else
      logger.debug("unknown event:#{event}")
    end

    @dispatcher.reap(reap_children) rescue nil
    @dispatcher.tick
  end
end

#term(_command) ⇒ Object



84
85
86
# File 'lib/main_loop/loop.rb', line 84

def term(_command)
  @dispatcher.term unless @dispatcher.terminating?
end

#wait2(pid) ⇒ Object

:nocov:



120
121
122
# File 'lib/main_loop/loop.rb', line 120

def wait2(pid)
  Process.wait2(pid, ::Process::WNOHANG)
end