module Unicorn::WorkerKiller::Oom

Public Class Methods

new(app, memory_limit_min = (1024**3), memory_limit_max = (2*(1024**3)), check_cycle = 16, verbose = false) click to toggle source

Killing the process must be occurred at the outside of the request. We're using similar techniques used by OobGC, to ensure actual killing doesn't affect the request.

@see github.com/defunkt/unicorn/blob/master/lib/unicorn/oob_gc.rb#L40

# File lib/unicorn/worker_killer.rb, line 36
def self.new(app, memory_limit_min = (1024**3), memory_limit_max = (2*(1024**3)), check_cycle = 16, verbose = false)
  ObjectSpace.each_object(Unicorn::HttpServer) do |s|
    s.extend(self)
    s.instance_variable_set(:@_worker_memory_limit_min, memory_limit_min)
    s.instance_variable_set(:@_worker_memory_limit_max, memory_limit_max)
    s.instance_variable_set(:@_worker_check_cycle, check_cycle)
    s.instance_variable_set(:@_worker_check_count, 0)
    s.instance_variable_set(:@_verbose, verbose)
  end
  app # pretend to be Rack middleware since it was in the past
end

Public Instance Methods

process_client(client) click to toggle source
Calls superclass method
# File lib/unicorn/worker_killer.rb, line 52
def process_client(client)
  super(client) # Unicorn::HttpServer#process_client
  return if @_worker_memory_limit_min == 0 && @_worker_memory_limit_max == 0

  @_worker_process_start ||= Time.now
  @_worker_memory_limit ||= @_worker_memory_limit_min + randomize(@_worker_memory_limit_max - @_worker_memory_limit_min + 1)
  @_worker_check_count += 1
  if @_worker_check_count % @_worker_check_cycle == 0
    rss = GetProcessMem.new.bytes
    logger.info "#{self}: worker (pid: #{Process.pid}) using #{rss} bytes." if @_verbose
    if rss > @_worker_memory_limit
      logger.warn "#{self}: worker (pid: #{Process.pid}) exceeds memory limit (#{rss} bytes > #{@_worker_memory_limit} bytes)"
      Unicorn::WorkerKiller.kill_self(logger, @_worker_process_start)
    end
    @_worker_check_count = 0
  end
end
randomize(integer) click to toggle source
# File lib/unicorn/worker_killer.rb, line 48
def randomize(integer)
  RUBY_VERSION > "1.9" ? Random.rand(integer.abs) : rand(integer)
end