def self.start(opts={})
@opts = opts
$WORKERS ||= []
parent = nil
@pids = {}
port = (opts[:socket] || opts[:port]).to_i
max_port = Merb::Config[:cluster] ? Merb::Config[:cluster] - 1 : 0
if max_port == 0
start_at_port(port)
return
end
$0 = process_title(:spawner, port)
catch(:new_worker) do
0.upto(max_port) do |i|
parent = spawn_worker(port + i)
end
end
return unless parent
0.upto(max_port) do |i|
Thread.new do
catch(:new_worker) do
loop do
pid, status = @pids[port + i], nil
poller = Merb::System::PortablePoller.new(pid)
begin
tick = 1
loop do
_, status = Process.wait2(pid, Process::WNOHANG)
break if status
if (tick % 120 == 0) && Merb::Config[:max_memory] && poller.memory > Merb::Config[:max_memory]
tick = 1
Process.kill("INT", pid)
if (Process.kill(0, pid) rescue false)
sleep Merb::Config[:hang_time] || 5
Process.kill(9, pid)
Process.wait2(pid) if (Process.kill(0, pid) rescue false)
end
status = Struct.new(:exitstatus).new(nil)
break
end
tick += 1
sleep 0.25
end
rescue SystemCallError => e
ensure
if !status ||
(status.exitstatus && status.exitstatus != 0) ||
Merb.exiting then
Thread.exit
end
end
spawn_worker(port + i)
end
end
end
end
sleep
end