summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2011-08-19 21:01:52 +0200
committerHelmut Grohne <helmut@subdivi.de>2011-08-19 21:01:52 +0200
commit6bb3c64529ab99866de5db70f06d00e2c50b30a5 (patch)
treeea60e6e325ed1c443b9d29f73d3b8e4599a636ea
parent8ab2290c24d90d5ff862b68455d0c7b88d5dedc1 (diff)
downloadwsgitools-6bb3c64529ab99866de5db70f06d00e2c50b30a5.tar.gz
scgi: support reusing a listen socket
This is useful when used in combination with e.g. systemd.
-rw-r--r--wsgitools/scgi/asynchronous.py21
-rw-r--r--wsgitools/scgi/forkpool.py23
2 files changed, 32 insertions, 12 deletions
diff --git a/wsgitools/scgi/asynchronous.py b/wsgitools/scgi/asynchronous.py
index 75f1ff0..e1dbcc6 100644
--- a/wsgitools/scgi/asynchronous.py
+++ b/wsgitools/scgi/asynchronous.py
@@ -191,7 +191,7 @@ class SCGIServer(asyncore.dispatcher):
multiple threads."""
def __init__(self, wsgiapp, port, interface="localhost", error=sys.stderr,
maxrequestsize=None, maxpostsize=None, blocksize=None,
- config={}):
+ config={}, reusesocket=None):
"""
@param wsgiapp: is the wsgi application to be run.
@type port: int
@@ -215,8 +215,16 @@ class SCGIServer(asyncore.dispatcher):
@type config: {}
@param config: the environ dictionary is updated using these values for
each request.
+ @type reusesocket: None or socket.socket
+ @param reusesocket: If a socket is passed, do not create a socket.
+ Instead use given socket as listen socket. The passed socket
+ must be set up for accepting tcp connections (i.e. AF_INET,
+ SOCK_STREAM with bind and listen called).
"""
- asyncore.dispatcher.__init__(self)
+ if reusesocket is None:
+ asyncore.dispatcher.__init__(self)
+ else:
+ asyncore.dispatcher.__init__(self, reusesocket)
self.wsgiapp = wsgiapp
self.error = error
@@ -229,10 +237,11 @@ class SCGIServer(asyncore.dispatcher):
self.conf["blocksize"] = blocksize
self.conf["config"] = config
- self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
- self.set_reuse_addr()
- self.bind((interface, port))
- self.listen(5)
+ if reusesocket is None:
+ self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.set_reuse_addr()
+ self.bind((interface, port))
+ self.listen(5)
def handle_accept(self):
"""asyncore interface"""
diff --git a/wsgitools/scgi/forkpool.py b/wsgitools/scgi/forkpool.py
index b090a54..8ccd579 100644
--- a/wsgitools/scgi/forkpool.py
+++ b/wsgitools/scgi/forkpool.py
@@ -168,7 +168,8 @@ class SCGIServer:
self.state = state
def __init__(self, wsgiapp, port, interface="localhost", error=sys.stderr,
- minworkers=2, maxworkers=32, maxrequests=1000, config={}):
+ minworkers=2, maxworkers=32, maxrequests=1000, config={},
+ reusesocket=None):
"""
@param wsgiapp: is the WSGI application to be run.
@type port: int
@@ -188,6 +189,11 @@ class SCGIServer:
@type config: {}
@param config: the environ dictionary is updated using these values for
each request.
+ @type reusesocket: None or socket.socket
+ @param reusesocket: If a socket is passed, do not create a socket.
+ Instead use given socket as listen socket. The passed socket
+ must be set up for accepting tcp connections (i.e. AF_INET,
+ SOCK_STREAM with bind and listen called).
"""
assert hasattr(error, "write")
self.wsgiapp = wsgiapp
@@ -198,6 +204,7 @@ class SCGIServer:
self.maxrequests = maxrequests
self.config = config
self.error = error
+ self.reusesocket = reusesocket
self.server = None # becomes a socket
# maps filedescriptors to WorkerStates
self.workers = {}
@@ -218,10 +225,13 @@ class SCGIServer:
"""
Serve the wsgi application.
"""
- self.server = socket.socket()
- self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.server.bind((self.interface, self.port))
- self.server.listen(5)
+ if self.reusesocket is None:
+ self.server = socket.socket()
+ self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.server.bind((self.interface, self.port))
+ self.server.listen(5)
+ else:
+ self.server = self.reusesocket
self.running = True
while self.running:
while (len(self.workers) < self.minworkers or # less than min
@@ -254,7 +264,8 @@ class SCGIServer:
pid, _ = os.waitpid(0, os.WNOHANG)
except OSError:
pass
- self.server.close()
+ if self.reusesocket is None:
+ self.server.close()
self.server = None
self.killworkers()