mirror of mongrel-development@rubyforge.org (inactive)
 help / color / mirror / Atom feed
From: Eric Wong <normalperson-rMlxZR9MS24@public.gmane.org>
To: mongrel-development-GrnCvJ7WPxnNLxjTenLetw@public.gmane.org
Subject: teaching Mongrel to inherit sockets (and replace mongrel_cluster)
Date: Thu, 13 Aug 2009 18:18:06 -0700	[thread overview]
Message-ID: <20090814011806.GA13323@dcvr.yhbt.net> (raw)

This change to Mongrel should be completely harmless for non-UNIX
systems, too (it won't break (or do) anything).

This minimal change let Mongrels inherit listen sockets from a parent
process, so that parent could be a cluster manager.  This means no more
port juggling with mongrel_cluster!  The entire Mongrel pack will all
share one port.

Only the manager script (see below) itself relies on UNIX-isms (but I
think mongrel_cluster did, too).

diff --git a/lib/mongrel.rb b/lib/mongrel.rb
index 0619abe..90e99e7 100644
--- a/lib/mongrel.rb
+++ b/lib/mongrel.rb
@@ -91,7 +91,11 @@ module Mongrel
     def initialize(host, port, num_processors=950, throttle=0, timeout=60)
       
       tries = 0
-      @socket = TCPServer.new(host, port) 
+      @socket = if ENV['LISTEN_FD']
+        TCPServer.for_fd(ENV['LISTEN_FD'].to_i)
+      else
+        TCPServer.new(host, port)
+      end
       if defined?(Fcntl::FD_CLOEXEC)
         @socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
       end
---

Here's my initial cut of a mongrel_cluster replacement, it can
definitely be cleaned up and improved upon with real option parsing and
such...

---------------------------------- 8< ----------------------------------
#!/usr/bin/env ruby
require 'socket'
nr_workers = 4
pids = {}
cmd = %w(mongrel_rails start)
server = TCPServer.new('0.0.0.0', 3000)
server.listen 1024
ENV['LISTEN_FD'] = server.fileno.to_s

# pass any signals we receive onto each child process:
%w(TERM INT USR1 USR2).each do |sig|
  trap(sig) do
    pids.keys.each { |pid| Process.kill(sig, pid) rescue nil }
    exit 0 if sig == 'TERM' || sig == 'INT' # TERM and INT mean death
  end
end

nr_workers.times { |i| pids[fork { exec *cmd }] = i }
loop do
  pid, status = Process.waitpid2(-1)
  i = pids.delete(pid) or next
  STDERR.puts "reaped worker #{i}: #{status}, respawning..."
  pids[fork { exec *cmd }] = i
end
---------------------------------- 8< ----------------------------------
-- 
Eric Wong

                 reply	other threads:[~2009-08-14  1:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed
replies disabled, historical list

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).