From 1b27d3f2b03d96567a9276c45d006c899e8dcb87 Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Mon, 4 Jul 2011 17:00:27 -0700 Subject: [PATCH] Add the HTTPServer.add_sockets interface --- tornado/httpserver.py | 45 +++++++++++++++++++++------------ tornado/test/httpclient_test.py | 2 +- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/tornado/httpserver.py b/tornado/httpserver.py index e590d678b..2fa325c1c 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -133,19 +133,35 @@ class HTTPServer(object): self.xheaders = xheaders self.ssl_options = ssl_options self._sockets = {} # fd -> socket object + self._pending_sockets = [] self._started = False def listen(self, port, address=""): - """Binds to the given port and starts the server in a single process. + """Starts accepting connections on the given port. - This method is a shortcut for: + This method may be called more than once to listen on multiple ports. + ``listen`` takes effect immediately; it is not necessary to call + `HTTPServer.start` afterwards. It is, however, necessary to start + the ``IOLoop``. + """ + sockets = netutil.bind_sockets(port, address=address) + self.add_sockets(sockets) - server.bind(port, address) - server.start(1) + def add_sockets(self, sockets): + """Makes this server start accepting connections on the given sockets. + The ``sockets`` parameter is a list of socket objects such as + those returned by `tornado.netutil.bind_sockets`. + ``add_sockets`` is typically used in combination with that + method and `tornado.process.fork_processes` to provide greater + control over the initialization of a multi-process server. """ - self.bind(port, address) - self.start(1) + if self.io_loop is None: + self.io_loop = ioloop.IOLoop.instance() + for sock in sockets: + self._sockets[sock.fileno()] = sock + self.io_loop.add_handler(sock.fileno(), self._handle_events, + ioloop.IOLoop.READ) def bind(self, port, address=None, family=socket.AF_UNSPEC, backlog=128): """Binds this server to the given port on the given address. @@ -169,11 +185,10 @@ class HTTPServer(object): """ sockets = netutil.bind_sockets(port, address=address, family=family, backlog=backlog) - for sock in sockets: - self._sockets[sock.fileno()] = sock - if self._started: - self.io_loop.add_handler(sock.fileno(), self._handle_events, - ioloop.IOLoop.READ) + if self._started: + self.add_sockets(sockets) + else: + self._pending_sockets.extend(sockets) def start(self, num_processes=1): """Starts this server in the IOLoop. @@ -198,11 +213,9 @@ class HTTPServer(object): self._started = True if num_processes != 1: process.fork_processes(num_processes) - if not self.io_loop: - self.io_loop = ioloop.IOLoop.instance() - for fd in self._sockets.keys(): - self.io_loop.add_handler(fd, self._handle_events, - ioloop.IOLoop.READ) + sockets = self._pending_sockets + self._pending_sockets = [] + self.add_sockets(sockets) def stop(self): """Stops listening for new connections. diff --git a/tornado/test/httpclient_test.py b/tornado/test/httpclient_test.py index c541818bb..b633de7b3 100644 --- a/tornado/test/httpclient_test.py +++ b/tornado/test/httpclient_test.py @@ -204,7 +204,7 @@ class HTTPClientCommonTestCase(AsyncHTTPTestCase, LogTrapTestCase): def test_ipv6(self): try: - self.http_server.bind(self.get_http_port(), address='::1') + self.http_server.listen(self.get_http_port(), address='::1') except socket.gaierror, e: if e.errno == socket.EAI_ADDRFAMILY: # ipv6 is not configured on this system, so skip this test -- 2.47.3