class ProcessManager::ChildrenMonitor

Attributes

options[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/process_manager/children_monitor.rb, line 16
def initialize(options = {})
  @options = options
  options[:logger] ||= Logger.new(STDOUT).tap do |logger|
    logger.level = Logger::INFO
  end
end
run_in_background(options = {}) click to toggle source
# File lib/process_manager/children_monitor.rb, line 4
def self.run_in_background(options = {})
  new(options).tap do |monitor|
    options[:interval] ||= 30
    Thread.new do
      loop do
        monitor.run
        sleep(options[:interval])
      end
    end
  end
end

Public Instance Methods

logger() click to toggle source
# File lib/process_manager/children_monitor.rb, line 37
def logger
  options[:logger]
end
run() click to toggle source
# File lib/process_manager/children_monitor.rb, line 23
def run
  children_pids.each do |pid|
    memory_usage = process_memory_usage(pid)
    if memory_usage > options[:memory_limit]
      logger.info("Child #{pid} uses #{memory_usage} MB of memory, graceful shutdown signaled.")
      gracefully_kill_child(pid)
    else
      logger.debug("Child #{pid} uses #{memory_usage} MB of memory.")
    end
  end
rescue => e
  logger.error(e)
end

Protected Instance Methods

children_pids() click to toggle source
# File lib/process_manager/children_monitor.rb, line 57
def children_pids
  ppid = parent_pid
  return [] unless ppid
  [].tap do |list|
    Dir["/proc/*/stat"].each do |path|
      data = File.read(path) rescue
      next unless data
      data = data.split(/\s+/)
      next unless data[3].to_i == ppid
      list << data[0].to_i
    end
  end
end
gracefully_kill_child(pid) click to toggle source
# File lib/process_manager/children_monitor.rb, line 71
def gracefully_kill_child(pid)
  # See http://unicorn.bogomips.org/SIGNALS.html
  # Gracefully exit after finishing the current request. The master process will respawn a worker to replace this one.
  Process.kill("QUIT", pid)
rescue Errno::ESRCH
  # noop
end
parent_pid() click to toggle source
# File lib/process_manager/children_monitor.rb, line 43
def parent_pid
  options[:parent_pid] || read_parent_pid
end
process_memory_usage(pid) click to toggle source
# File lib/process_manager/children_monitor.rb, line 53
def process_memory_usage(pid)
  File.read("/proc/#{pid}/statm").split(/\s+/)[1].to_i * 4096 / 1024 / 1024
end
read_parent_pid() click to toggle source
# File lib/process_manager/children_monitor.rb, line 47
def read_parent_pid
  File.read(options[:parent_pid_path]).to_i
rescue Errno::ENOENT
  nil
end