From 990037181347adf4e238915bbb5513875bc52517 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sat, 16 Jan 2010 03:20:11 +0100 Subject: [PATCH] some fixes --- gunicorn/arbiter.py | 7 ++++--- gunicorn/http/http_parser.py | 4 +++- gunicorn/http/request.py | 6 ++++-- gunicorn/http/response.py | 32 +++++++++++++++++++------------- gunicorn/worker.py | 18 +++++++++--------- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 11546619..8effce12 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -49,7 +49,7 @@ class Arbiter(object): SIG_QUEUE = [] SIGNALS = map( lambda x: getattr(signal, "SIG%s" % x), - "CHLD HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCH".split() + "HUP QUIT INT TERM TTIN TTOU USR1 USR2 WINCH".split() ) SIG_NAMES = dict( (getattr(signal, name), name[3:].lower()) for name in dir(signal) @@ -74,6 +74,7 @@ class Arbiter(object): map(self.set_non_blocking, pair) map(lambda p: fcntl.fcntl(p, fcntl.F_SETFD, fcntl.FD_CLOEXEC), pair) map(lambda s: signal.signal(s, self.signal), self.SIGNALS) + signal.signal(signal.SIGCHLD, self.handle_chld) def set_non_blocking(self, fd): flags = fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK @@ -125,7 +126,7 @@ class Arbiter(object): sock.listen(2048) return sock - def set_sockopts(self, sock): + def set_sockopts(self, sock): sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) if hasattr(socket, "TCP_CORK"): @@ -170,7 +171,7 @@ class Arbiter(object): log.info("Master is shutting down.") self.stop() - def handle_chld(self): + def handle_chld(self, sig, frame): self.wakeup() def handle_hup(self): diff --git a/gunicorn/http/http_parser.py b/gunicorn/http/http_parser.py index 689272f1..a9d2f934 100644 --- a/gunicorn/http/http_parser.py +++ b/gunicorn/http/http_parser.py @@ -37,6 +37,8 @@ class HttpParser(object): """ take a string buff. It return environ or None if parsing isn't done. """ + if self._headers: + return self._headers # wee could be smarter here # by just reading the array, but converting @@ -69,7 +71,7 @@ class HttpParser(object): except ValueError: # bad headers pass - headers = self._headers + headers.update(self._headers) self._content_len = int(self._headers.get('Content-Length') or 0) return headers diff --git a/gunicorn/http/request.py b/gunicorn/http/request.py index 3d7e7ea9..3c186d4f 100644 --- a/gunicorn/http/request.py +++ b/gunicorn/http/request.py @@ -55,7 +55,7 @@ class HTTPRequest(object): SERVER_VERSION = "gunicorn/%s" % __version__ def __init__(self, socket, client_address, server_address): - self.socket = socket + self.socket = socket.dup() self.client_address = client_address self.server_address = server_address self.response_status = None @@ -69,12 +69,14 @@ class HTTPRequest(object): remain = CHUNK_SIZE buf = create_string_buffer(remain) remain -= self.socket.recv_into(buf, remain) + while not self.parser.headers(headers, buf): data = create_string_buffer(remain) remain -= self.socket.recv_into(data, remain) buf = create_string_buffer(data.value + buf.value) - if headers.get('Accept', '').lower() == "100-continue": + print headers + if headers.get('Except', '').lower() == "100-continue": self.socket.send("100 Continue\n") if "?" in self.parser.path: diff --git a/gunicorn/http/response.py b/gunicorn/http/response.py index 1b2b120f..07442f53 100644 --- a/gunicorn/http/response.py +++ b/gunicorn/http/response.py @@ -24,35 +24,41 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. +import time + from gunicorn.util import http_date class HTTPResponse(object): - def __init__(self, req, data): - self.req = req - self.data = data - self.headers = self.req.response_headers or {} + def __init__(self, sock, response, req): + self.sock = sock + self.data = response + self.headers = req.response_headers or {} + self.status = req.response_status + self.SERVER_VERSION = req.SERVER_VERSION def send(self): # send headers resp_head = [] - resp_head.append("%s %ss\r\n" % (self.req.parser.version, self.req.response_status)) + resp_head.append("HTTP/1.1 %s\r\n" % (self.status)) - resp_head.append("Server: %s\r\n" % self.req.SERVER_VERSION) + resp_head.append("Server: %s\r\n" % self.SERVER_VERSION) resp_head.append("Date: %s\r\n" % http_date()) # broken clients - resp_head.append("Status: %s\r\n" % str(self.req.response_status)) + resp_head.append("Status: %s\r\n" % str(self.status)) # always close the conenction resp_head.append("Connection: close\r\n") - for name, value in self.req.response_headers.items(): + for name, value in self.headers.items(): resp_head.append("%s: %s\r\n" % (name, value)) - self.req.socket.send("%s\r\n" % "".join(resp_head)) + + self.sock.send("%s\r\n" % "".join(resp_head)) - for chunk in self.data: - self.req.socket.send(chunk) - self.req.socket.close() + for chunk in self.data: + self.sock.send(chunk) + + print "sent" + self.sock.close() if hasattr(self.data, "close"): self.data.close() - \ No newline at end of file diff --git a/gunicorn/worker.py b/gunicorn/worker.py index 81fac28e..02d30ba2 100644 --- a/gunicorn/worker.py +++ b/gunicorn/worker.py @@ -106,36 +106,36 @@ class Worker(object): return raise + # 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: - #time.sleep(0.01) try: + conn, addr = self.socket.accept() conn.setblocking(1) - + + # handle connection + self.handle(conn, addr) + + # Update the fd mtime on each client completion # to signal that this worker process is alive. spinner = (spinner+1) % 2 self._fchmod(spinner) - - # handle connection - self.handle(conn, addr) except socket.error, e: if e[0] in [errno.EAGAIN, errno.ECONNABORTED]: break # Uh oh! raise - def handle(self, conn, client): self.close_on_exec(conn) try: req = http.HTTPRequest(conn, client, self.address) - result = self.app(req.read(), req.start_response) - response = http.HTTPResponse(req, result) - response.send() + response = self.app(req.read(), req.start_response) + http.HTTPResponse(conn, response, req).send() except Exception, e: log.exception("Error processing request. [%s]" % str(e)) if e[0] == 32: