public
Created

for khaase

  • Download Gist
rackup.multiprocess
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#!/usr/bin/ruby
 
require "rticulate-env"
require "sequel"
require "memcache"
require 'pp'
 
url=URI.parse(Env['rackurl'])
start_port=url.port;
rack_workers=Env['rack_workers'] || 3;
 
# this trick from http://stackoverflow.com/questions/42566/getting-the-hostname-or-ip-in-ruby-on-rails
#
local_addr=UDPSocket.open {|s| s.connect('10.0.0.1',1); s.addr.last }
 
if pid=Env['pidfile'] then
File.open(pid,"w") do |f|
f.print "#{Process.pid}\n"
end
end
 
syslog=IO.popen("logger -t 'rticulate' -p local1.info","w")
syslog.sync=true
 
 
def new_child(host,port,syslog)
Kernel.fork do
Object.const_set "CACHE", MemCache.new(Env['memcached'])
Object.const_set "DB", Sequel.connect(Env['database'])
require "rticulate"
require "app/rack-app"
$stdout.reopen(syslog)
$stderr.reopen(syslog)
$stdin.reopen("/dev/null")
DB << "insert into varnish_backends (address) values ('#{host}:#{port}');"
DB << "notify varnish;"
 
# This needs to be a signal that thin/eventmachine doesn't steal
# the handling of (TERM and INT are apparently no good). Seems a
# reasonable assumption that we won't get a real SIGWINCH after
# closing std*
Signal.trap("WINCH") do
warn "Terminating #{$$}"
DB << "delete from varnish_backends where address='#{host}:#{port}';"
exit 0
end
Rack::Handler::Thin.run(Rticulate.rack_app,
:Host=>host, :Port=>port) do |s|
warn s
end
end
end
 
def kill_kids(ports)
ports.keys.each do |pid|
Process.kill("WINCH",pid)
end
end
 
respawn=true
ports={}
rack_workers.times do |i|
kid=new_child(local_addr,start_port+i,syslog)
ports[kid]=start_port+i
sleep 1.5 # avoid thrashing quite as monstrously
end
warn "$0 starting with #{rack_workers} workers: pids "+ports.inspect
 
Signal.trap("TERM") do
warn "Terminating children"
respawn=false
kill_kids ports
end
 
Signal.trap("HUP") do
warn "Restarting children"
kill_kids ports
end
 
until ports.empty?
died=Process.wait
warn "Worker #{died} died"
port= ports[died]
ports.delete(died)
if respawn then
ports[new_child(local_addr,port,syslog)]=port
end
end
 
pid and File.delete pid

An much more useful version of this can be found at https://github.com/telent/thin-prefork

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.