From 7715199b482cd63768c1ef63f0c0732437e6bd00 Mon Sep 17 00:00:00 2001 From: benoitc Date: Thu, 2 Sep 2010 14:55:56 +0200 Subject: [PATCH] it's better to test when you use the right code to do it. We had a blocking operation django example (we read a file already on the fs and recreate another which blocked async schedulers). While I'm here ease the code of eventlet worker. Just use the convenient eventlet.serve function which already manage what we do and revert sopme useless changes in body and header parsing. --- examples/frameworks/djangotest/settings.py | 5 ++ .../frameworks/djangotest/testing/views.py | 7 +-- gunicorn/arbiter.py | 2 +- gunicorn/http/body.py | 3 +- gunicorn/http/message.py | 10 +--- gunicorn/workers/geventlet.py | 60 +++++-------------- gunicorn/workers/ggevent.py | 17 ++++-- 7 files changed, 39 insertions(+), 65 deletions(-) diff --git a/examples/frameworks/djangotest/settings.py b/examples/frameworks/djangotest/settings.py index c7400265..30763f65 100755 --- a/examples/frameworks/djangotest/settings.py +++ b/examples/frameworks/djangotest/settings.py @@ -66,6 +66,11 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.auth.middleware.AuthenticationMiddleware', ) + +FILE_UPLOAD_HANDLERS = ( + "django.core.files.uploadhandler.TemporaryFileUploadHandler", +) + ROOT_URLCONF = 'djangotest.urls' TEMPLATE_DIRS = ( diff --git a/examples/frameworks/djangotest/testing/views.py b/examples/frameworks/djangotest/testing/views.py index 1b79b63d..06018b72 100755 --- a/examples/frameworks/djangotest/testing/views.py +++ b/examples/frameworks/djangotest/testing/views.py @@ -18,6 +18,7 @@ def home(request): subject = None message = None size = 0 + print request.META if request.POST: form = MsgForm(request.POST, request.FILES) print request.FILES @@ -25,11 +26,7 @@ def home(request): subject = form.cleaned_data['subject'] message = form.cleaned_data['message'] f = request.FILES['f'] - tmp = tempfile.TemporaryFile() - for chunk in f.chunks(): - tmp.write(chunk) - tmp.flush() - size = int(os.fstat(tmp.fileno())[6]) + size = int(os.fstat(f.fileno())[6]) else: form = MsgForm() diff --git a/gunicorn/arbiter.py b/gunicorn/arbiter.py index 96a9dc58..9002af8c 100644 --- a/gunicorn/arbiter.py +++ b/gunicorn/arbiter.py @@ -450,7 +450,7 @@ class Arbiter(object): os.unlink(worker.tmpname) except: pass - + def spawn_workers(self): """\ Spawn new workers as needed. diff --git a/gunicorn/http/body.py b/gunicorn/http/body.py index 585790d8..eea3d481 100644 --- a/gunicorn/http/body.py +++ b/gunicorn/http/body.py @@ -223,12 +223,11 @@ class Body(object): idx = self.buf.getvalue().find("\n") while idx < 0: - pos = self.buf.tell() - 1 data = self.reader.read(1024) if not len(data): break self.buf.write(data) - idx = self.buf.getvalue()[pos:].find("\n") + idx = self.buf.getvalue().find("\n") if size < self.buf.tell(): break diff --git a/gunicorn/http/message.py b/gunicorn/http/message.py index e31844df..7168aaa5 100644 --- a/gunicorn/http/message.py +++ b/gunicorn/http/message.py @@ -137,25 +137,21 @@ class Request(Message): # Headers - pos = 0 idx = buf.getvalue().find("\r\n\r\n") done = buf.getvalue()[:2] == "\r\n" while idx < 0 and not done: - pos = buf.tell() - 4 self.get_data(unreader, buf) - idx = buf.getvalue()[pos:].find("\r\n\r\n") + idx = buf.getvalue().find("\r\n\r\n") done = buf.getvalue()[:2] == "\r\n" if done: self.unreader.unread(buf.getvalue()[2:]) return "" - end = pos + idx - - self.headers = self.parse_headers(buf.getvalue()[:end]) + self.headers = self.parse_headers(buf.getvalue()[:idx]) - ret = buf.getvalue()[end+4:] + ret = buf.getvalue()[idx+4:] buf.truncate(0) return ret diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py index f465a4ef..027e8141 100644 --- a/gunicorn/workers/geventlet.py +++ b/gunicorn/workers/geventlet.py @@ -5,15 +5,13 @@ from __future__ import with_statement -import errno -import socket + +import os import eventlet -from eventlet.green import os from eventlet import hubs from eventlet.greenio import GreenSocket - from gunicorn.workers.async import AsyncWorker class EventletWorker(AsyncWorker): @@ -24,55 +22,29 @@ class EventletWorker(AsyncWorker): if eventlet.version_info < (0,9,7): raise RuntimeError("You need eventlet >= 0.9.7") eventlet.monkey_patch(os=False) - + def init_process(self): hubs.use_hub() super(EventletWorker, self).init_process() def timeout_ctx(self): - return eventlet.Timeout(self.cfg.keepalive, False) - - def acceptor(self, pool): - try: - while self.alive: - try: - client, addr = self.socket.accept() - pool.spawn_n(self.handle, client, addr) - except socket.error, e: - if e[0] not in (errno.EAGAIN, errno.ECONNABORTED): - raise - - if pool.running() > self.worker_connections: - continue - - try: - hubs.trampoline(self.socket.fileno(), read=True, - timeout=self.timeout) - except eventlet.Timeout: - pass - except eventlet.StopServe: - pool.waitall() + return eventlet.Timeout(self.cfg.keepalive, False) def run(self): self.socket = GreenSocket(family_or_realsock=self.socket.sock) self.socket.setblocking(1) + self.acceptor = eventlet.spawn(eventlet.serve, self.socket, + self.handle, self.worker_connections) - pool = eventlet.GreenPool(self.worker_connections) - - acceptor = eventlet.spawn(self.acceptor, pool) - - try: - while self.alive: - self.notify() - - if self.ppid != os.getppid(): - self.log.info("Parent changed, shutting down: %s" % self) - server.stop() - break - eventlet.sleep(0.1) - except KeyboardInterrupt: - pass + while self.alive: + self.notify() + if self.ppid != os.getppid(): + self.log.info("Parent changed, shutting down: %s" % self) + break + eventlet.sleep(0.1) + self.notify() with eventlet.Timeout(self.timeout, False): - eventlet.kill(acceptor, eventlet.StopServe) - + self.log.info("are we blocking?") + eventlet.kill(self.acceptor, eventlet.StopServe) + self.log.info("no sir!") diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index b4eee704..40e164d5 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -77,15 +77,17 @@ class GeventWorker(AsyncWorker): if self.ppid != os.getppid(): self.log.info("Parent changed, shutting down: %s" % self) break - gevent.sleep(0.1) - + gevent.sleep(0.1) + except KeyboardInterrupt: + pass + + try: # Try to stop connections until timeout self.notify() server.stop(timeout=self.timeout) except: pass - def handle_request(self, *args): try: super(GeventWorker, self).handle_request(*args) @@ -137,11 +139,14 @@ class GeventBaseWorker(Worker): break gevent.sleep(0.1) + except KeyboardInterrupt: + pass + + # try to stop the connections + try: self.notify() server.stop(timeout=self.timeout) - except gevent.GreenletExit: - pass - except KeyboardInterrupt: + except: pass