From db01c210a2afd52ad4b373bb54c3e211c01cd99a Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 20 Jan 2010 18:06:35 +0100 Subject: [PATCH] Set blocking to 0 back since we prevented inheritence of the socket the socket. --- gunicorn/arbiter.py | 3 +- gunicorn/http/request.py | 12 ++++---- gunicorn/http/tee.py | 7 +++-- gunicorn/util.py | 6 ++-- gunicorn/worker.py | 60 +++++++++++++++++++++++----------------- tests/001-test-parser.py | 1 + 6 files changed, 52 insertions(+), 37 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 743577e9..b41ea3d9 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -135,7 +135,8 @@ class Arbiter(object): log.error("Unhandled signal: %s" % signame) continue log.info("Handling signal: %s" % signame) - handler() + handler() + self.wakeup() except StopIteration: break except KeyboardInterrupt: diff --git a/gunicorn/http/request.py b/gunicorn/http/request.py index f2e08bc6..5442e45a 100644 --- a/gunicorn/http/request.py +++ b/gunicorn/http/request.py @@ -17,13 +17,14 @@ import logging from gunicorn import __version__ from gunicorn.http.http_parser import HttpParser from gunicorn.http.tee import TeeInput -from gunicorn.util import CHUNK_SIZE, read_partial, normalize_name +from gunicorn.util import CHUNK_SIZE, read_partial, \ +normalize_name NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') - +log = logging.getLogger(__name__) class RequestError(Exception): @@ -57,7 +58,7 @@ class HTTPRequest(object): self.parser = HttpParser() self.start_response_called = False - self.log = logging.getLogger(__name__) + def read(self): environ = {} @@ -75,13 +76,12 @@ class HTTPRequest(object): if i != -1: break if not headers: - print "ici :()" environ.update(self.DEFAULTS) return environ - self.log.info("%s", self.parser.status) + log.info("%s", self.parser.status) - self.log.info("Got headers:\n%s" % headers) + log.info("Got headers:\n%s" % headers) if self.parser.headers_dict.get('Except', '').lower() == "100-continue": self.socket.send("100 Continue\n") diff --git a/gunicorn/http/tee.py b/gunicorn/http/tee.py index ef094683..20c70b4d 100644 --- a/gunicorn/http/tee.py +++ b/gunicorn/http/tee.py @@ -122,12 +122,13 @@ class TeeInput(object): data = read_partial(self.socket, length) self.buf += data chunk, self.buf = self.parser.filter_body(self.buf) - print self.buf if chunk: - print chunk self.tmp.write(chunk) self.tmp.seek(0, os.SEEK_END) return chunk + if not data: + self._is_socket = False + break self._finalize() return "" @@ -136,7 +137,7 @@ class TeeInput(object): if any.""" if self.parser.body_eof(): # handle trailing headers - if self.parser.is_chunked: + if self.parser.is_chunked and self._is_socket: while not self.parser.trailing_header(self.buf): data = read_partial(self.socket, CHUNK_SIZE) if not data: break diff --git a/gunicorn/util.py b/gunicorn/util.py index c4ee918a..a2766011 100644 --- a/gunicorn/util.py +++ b/gunicorn/util.py @@ -8,6 +8,7 @@ import select import socket import time + timeout_default = object() CHUNK_SIZE = (16 * 1024) @@ -37,14 +38,15 @@ def close(sock): def read_partial(sock, length): while True: try: - ret = select.select([sock.fileno()], [], []) + ret = select.select([sock.fileno()], [], [], 0) if ret[0]: break except select.error, e: if e[0] == errno.EINTR: - break + continue raise data = sock.recv(length) return data + def write(sock, data): buf = "" diff --git a/gunicorn/worker.py b/gunicorn/worker.py index d2b83190..572f90a0 100644 --- a/gunicorn/worker.py +++ b/gunicorn/worker.py @@ -18,6 +18,8 @@ import time from gunicorn import http from gunicorn import util +log = logging.getLogger(__name__) + class Worker(object): SIGNALS = map( @@ -37,14 +39,19 @@ class Worker(object): self.close_on_exec(socket) self.close_on_exec(fd) + + # Set blocking to 0 back since we + # prevented inheritence of the socket + # the socket. + socket.setblocking(0) + self.socket = socket self.address = socket.getsockname() self.app = app self.alive = True - self.log = logging.getLogger(__name__) - + def close_on_exec(self, fd): flags = fcntl.fcntl(fd, fcntl.F_GETFD) | fcntl.FD_CLOEXEC fcntl.fcntl(fd, fcntl.F_SETFL, flags) @@ -72,6 +79,31 @@ class Worker(object): self.init_signals() spinner = 0 while self.alive: + + nr = 0 + # Accept until we hit EAGAIN. We're betting that when we're + # processing clients that more clients are waiting. When + # there's no more clients waiting we go back to the select() + # loop and wait for some lovin. + while self.alive: + try: + client, addr = self.socket.accept() + + + # handle connection + self.handle(client, addr) + + # Update the fd mtime on each client completion + # to signal that this worker process is alive. + spinner = (spinner+1) % 2 + self._fchmod(spinner) + nr += 1 + except socket.error, e: + if e[0] in [errno.EAGAIN, errno.ECONNABORTED, + errno.EWOULDBLOCK]: + break # Uh oh! + raise + if nr == 0: break while self.alive: spinner = (spinner+1) % 2 @@ -90,28 +122,6 @@ class Worker(object): spinner = (spinner+1) % 2 self._fchmod(spinner) - - # Accept until we hit EAGAIN. We're betting that when we're - # processing clients that more clients are waiting. When - # there's no more clients waiting we go back to the select() - # loop and wait for some lovin. - while self.alive: - try: - client, addr = self.socket.accept() - client.setblocking(0) - - # handle connection - self.handle(client, addr) - - # Update the fd mtime on each client completion - # to signal that this worker process is alive. - spinner = (spinner+1) % 2 - self._fchmod(spinner) - except socket.error, e: - if e[0] in [errno.EAGAIN, errno.ECONNABORTED, - errno.EWOULDBLOCK]: - break # Uh oh! - raise def handle(self, client, addr): self.close_on_exec(client) @@ -120,7 +130,7 @@ class Worker(object): response = self.app(req.read(), req.start_response) http.HTTPResponse(client, response, req).send() except Exception, e: - self.log.exception("Error processing request. [%s]" % str(e)) + log.exception("Error processing request. [%s]" % str(e)) # try to send something if an error happend msg = "HTTP/1.1 500 Internal Server Error\r\n\r\n" util.write_nonblock(client, msg) diff --git a/tests/001-test-parser.py b/tests/001-test-parser.py index 5f4417a8..8f9bb0a6 100644 --- a/tests/001-test-parser.py +++ b/tests/001-test-parser.py @@ -17,6 +17,7 @@ def test_001(buf, p): ]) body, tr = p.filter_body(buf[i:]) t.eq(body, '{"nom": "nom"}') + print t.eq(p.body_eof(), True) @t.request("002.http") def test_002(buf, p):