branch to handle unix sockets

This commit is contained in:
Benoit Chesneau 2010-02-03 13:35:32 +01:00
parent e804f97f5e
commit 0935ab3344
3 changed files with 68 additions and 43 deletions

View File

@ -140,7 +140,7 @@ class Arbiter(object):
self.log.error("should be a non GUNICORN environnement")
else:
raise
for i in range(5):
try:
sock = self.init_socket(addr)
@ -152,30 +152,46 @@ class Arbiter(object):
if i < 5:
self.log.error("Retrying in 1 second.")
time.sleep(1)
if self.LISTENER:
self.log.info("Listen on %s:%s" % self.LISTENER.getsockname())
if self.LISTENER:
try:
self.log.info("Listen on %s:%s" % self.LISTENER.getsockname())
except TypeError:
self.log.info("Listen on %s" % self.LISTENER.getsockname())
def init_socket_fromfd(self, fd, address):
sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
self.set_sockopts(sock)
if isinstance(address, basestring):
sock = socket.fromfd(fd, socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
self.set_tcp_sockopts(sock)
self.set_sockopts(sock, address)
return sock
def init_socket(self, address):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_sockopts(sock)
sock.bind(address)
sock.listen(2048)
if isinstance(address, basestring):
try:
os.remove(address)
except OSError:
pass
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_tcp_sockopts(sock)
self.set_sockopts(sock, address)
return sock
def set_sockopts(self, sock):
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
def set_tcp_sockopts(self, sock):
if hasattr(socket, "TCP_CORK"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 1)
elif hasattr(socket, "TCP_NOPUSH"):
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NOPUSH, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
def set_sockopts(self, sock, address):
sock.setblocking(0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(address)
sock.listen(2048)
def run(self):
self.start()
self.manage_workers()

View File

@ -28,10 +28,8 @@ UMASK = 0
def options():
return [
op.make_option('--host', dest='host',
help='Host to listen on. [%default]'),
op.make_option('--port', dest='port', type='int',
help='Port to listen on. [%default]'),
op.make_option('-b', '--bind', dest='bind',
help='Adress to listen on. Ex. host:port or unix://path/to/socketfile'),
op.make_option('--workers', dest='workers', type='int',
help='Number of workers to spawn. [%default]'),
op.make_option('-p','--pid', dest='pidfile',
@ -95,21 +93,26 @@ def main(usage, get_app):
if opts.debug:
workers = 1
host = opts.host or '127.0.0.1'
port = opts.port
if port is None:
if ':' in host:
host, port = host.split(':', 1)
bind = opts.bind or '127.0.0.1'
if bind.startswith("unix:"):
addr = bind.split("unix:")[1]
else:
if ':' in bind:
host, port = bind.split(':', 1)
if not port.isdigit():
raise RuntimeError("%r is not a valid port number." % port)
port = int(port)
else:
host = bind
port = 8000
addr = (host, port)
kwargs = dict(
debug=opts.debug,
pidfile=opts.pidfile
)
arbiter = Arbiter((host,port), workers, app,
arbiter = Arbiter(addr, workers, app,
**kwargs)
if opts.daemon:
daemonize()
@ -229,8 +232,9 @@ def run_paster():
else:
workers = int(ctx.local_conf.get('workers', 1))
opts.host = opts.host or ctx.local_conf.get('host', '127.0.0.1')
opts.port = opts.port or int(ctx.local_conf.get('port', 8000))
host = opts.host or ctx.local_conf.get('host', '127.0.0.1')
port = opts.port or int(ctx.local_conf.get('port', 8000))
bind = "%s:%s" % (host, port)
debug = ctx.global_conf.get('debug') == "true"
if debug:

View File

@ -30,7 +30,7 @@ class Command(BaseCommand):
help='Run daemonized in the background.'),
)
help = "Starts a fully-functional Web server using gunicorn."
args = '[optional port number, or ipaddr:port]'
args = '[optional port number, or ipaddr:port or unix:/path/to/sockfile]'
# Validation is called explicitly each time the server is reloaded.
requires_model_validation = False
@ -38,20 +38,21 @@ class Command(BaseCommand):
def handle(self, addrport='', *args, **options):
if args:
raise CommandError('Usage is runserver %s' % self.args)
if not addrport:
addr = ''
port = '8000'
bind = addrport or '127.0.0.1'
if bind.startswith("unix:"):
addr = bind.split("unix:")[1]
else:
try:
addr, port = addrport.split(':')
except ValueError:
addr, port = '', addrport
if not addr:
addr = '127.0.0.1'
if not port.isdigit():
raise CommandError("%r is not a valid port number." % port)
if ':' in bind:
host, port = host.split(':', 1)
if not port.isdigit():
raise CommandError("%r is not a valid port number." % port)
port = int(port)
else:
host = bind
port = 8000
addr = (host, port)
admin_media_path = options.get('admin_media_path', '')
workers = int(options.get('workers', '1'))
daemon = options.get('daemon')
@ -61,7 +62,11 @@ class Command(BaseCommand):
print "Validating models..."
self.validate(display_num_errors=True)
print "\nDjango version %s, using settings %r" % (django.get_version(), settings.SETTINGS_MODULE)
print "Development server is running at http://%s:%s/" % (addr, port)
if isinstance(address, basestring):
print "Development server is running at unix:/" % addr
else:
print "Development server is running at http://%s:%s/" % addr
print "Quit the server with %s." % quit_command
# django.core.management.base forces the locale to en-us.
@ -69,7 +74,7 @@ class Command(BaseCommand):
try:
handler = AdminMediaHandler(WSGIHandler(), admin_media_path)
arbiter = Arbiter((addr, int(port)), workers, handler,
arbiter = Arbiter(addr, workers, handler,
pidfile=pidfile)
if daemon:
daemonize()