class CrapServer::Forker

Handle preforking task. Will spawn 1 process per core.

Public Class Methods

new(sockets) click to toggle source
# File lib/crap_server/forker.rb, line 5
def initialize(sockets)
  @sockets = sockets
end

Public Instance Methods

run(&block) click to toggle source

Initialize

# File lib/crap_server/forker.rb, line 10
def run(&block)
  begin
    @block_proc = block
    @child_pids = []
    processor_count.times do
      @child_pids << spawn_child
    end

    check_children
  # If someone kill us, we kill our children. Yes, is sad, but we must do it :'(
  rescue ::Exception # If any kind of error happens, we must kill our children
    @child_pids.each do |cpid|
      begin
        # We send Ctrl+C to the process
        Process.kill(:INT, cpid)
      # If the process in not running or because any reason we have no privileges to kill him
      # We just only don't care. In any case, we can do nothing
      rescue Errno::ESRCH
      end
    end
    @sockets.each do |socket|
      # Shuts down communication on all copies of the connection.
      socket.shutdown
      socket.close
    end
  end
end

Protected Instance Methods

check_children() click to toggle source

The main loop that check if any process is killed. If one of them get killed, we spawn another one.

# File lib/crap_server/forker.rb, line 53
def check_children
  # We take care of our children. If someone kill one, me made another one.
  # PS: Is a hard work :P
  loop do
    pid = Process.wait
    @child_pids.delete(pid)
    @child_pids << spawn_child
  end
end
processor_count() click to toggle source

Extracted from github.com/grosser/parallel/blob/master/lib/parallel.rb Number of processors seen by the OS and used for process scheduling.

  • AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev

  • BSD: /sbin/sysctl

  • Cygwin: /proc/cpuinfo

  • Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl

  • HP-UX: /usr/sbin/ioscan

  • IRIX: /usr/sbin/sysconf

  • Linux: /proc/cpuinfo

  • Minix 3+: /proc/cpuinfo

  • Solaris: /usr/sbin/psrinfo

  • Tru64 UNIX: /usr/sbin/psrinfo

  • UnixWare: /usr/sbin/psrinfo

# File lib/crap_server/forker.rb, line 78
def processor_count
  @processor_count ||= begin
    os_name = RbConfig::CONFIG["target_os"]
    if os_name =~ /mingw|mswin/
      require 'win32ole'
      result = WIN32OLE.connect("winmgmts://").ExecQuery(
          "select NumberOfLogicalProcessors from Win32_Processor")
      result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
    elsif File.readable?("/proc/cpuinfo")
      IO.read("/proc/cpuinfo").scan(/^processor/).size
    elsif File.executable?("/usr/bin/hwprefs")
      IO.popen("/usr/bin/hwprefs thread_count").read.to_i
    elsif File.executable?("/usr/sbin/psrinfo")
      IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
    elsif File.executable?("/usr/sbin/ioscan")
      IO.popen("/usr/sbin/ioscan -kC processor") do |out|
        out.read.scan(/^.*processor/).size
      end
    elsif File.executable?("/usr/sbin/pmcycles")
      IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
    elsif File.executable?("/usr/sbin/lsdev")
      IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
    elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
      IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
    elsif File.executable?("/usr/sbin/sysctl")
      IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
    elsif File.executable?("/sbin/sysctl")
      IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
    else
      $stderr.puts "Unknown platform: " + RbConfig::CONFIG["target_os"]
      $stderr.puts "Assuming 1 processor."
      1
    end
  end
end
spawn_child() click to toggle source

Spawn a new Thread Pool in each process

# File lib/crap_server/forker.rb, line 41
def spawn_child
  fork do
    begin
      CrapServer::Application.send(:per_process_block).call if not CrapServer::Application.send(:per_process_block).nil?
      pool = CrapServer::ThreadPool.new @sockets
      pool.run &@block_proc
    rescue Interrupt
    end
  end
end