From 0a46d09c6ed1d77cf48d9706f6fa3577fab126ef Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Tue, 11 May 2010 23:33:48 -0400 Subject: [PATCH] Avoid a deadlock when the acceptor loop raises. An out of file descriptors error was causing the async acceptor loops to die. The notification process was unaffected so the workers didn't die. Async workers hitting an error in the acceptor now kill themselves and rely on the arbiter to restart a new worker in their stead. --- THANKS | 1 + examples/bad.py | 6 ++++++ gunicorn/workers/async.py | 4 ++-- gunicorn/workers/geventlet.py | 3 +++ gunicorn/workers/ggevent.py | 3 +++ 5 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 examples/bad.py diff --git a/THANKS b/THANKS index 800302f2..20554878 100644 --- a/THANKS +++ b/THANKS @@ -10,3 +10,4 @@ Johan Bergström Xavier Grangier Sergey Shepelev Chris Dent +Matt Good diff --git a/examples/bad.py b/examples/bad.py new file mode 100644 index 00000000..e39291ee --- /dev/null +++ b/examples/bad.py @@ -0,0 +1,6 @@ +import tempfile +files = [] +def app(environ, start_response): + files.append(tempfile.mkstemp()) + start_response('200 OK', [('Content-type', 'text/plain'), ('Content-length', '2')]) + return ['ok'] diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py index 76a53cb7..999d9622 100644 --- a/gunicorn/workers/async.py +++ b/gunicorn/workers/async.py @@ -30,7 +30,7 @@ class AsyncWorker(Worker): pass except socket.error, e: if e[0] not in (errno.EPIPE, errno.ECONNRESET): - self.log.exception("Error processing request.") + self.log.exception("Socket error processing request.") else: if e[0] == errno.ECONNRESET: self.log.warn("Ignoring connection reset") @@ -39,7 +39,7 @@ class AsyncWorker(Worker): except UnexpectedEOF: self.log.exception("Client closed the connection unexpectedly.") except Exception, e: - self.log.exception("Error processing request.") + self.log.exception("General error processing request.") try: # Last ditch attempt to notify the client of an error. mesg = "HTTP/1.0 500 Internal Server Error\r\n\r\n" diff --git a/gunicorn/workers/geventlet.py b/gunicorn/workers/geventlet.py index 5f870af8..35e0340e 100644 --- a/gunicorn/workers/geventlet.py +++ b/gunicorn/workers/geventlet.py @@ -62,6 +62,9 @@ class EventletWorker(AsyncWorker): conn, addr, gt = None, None, None except eventlet.StopServe: return + except: + self.log.exception("Unexpected error in acceptor. Sepuku.") + os._exit(4) def cleanup(self, thread, conn): try: diff --git a/gunicorn/workers/ggevent.py b/gunicorn/workers/ggevent.py index 89ff95e1..91968e24 100644 --- a/gunicorn/workers/ggevent.py +++ b/gunicorn/workers/ggevent.py @@ -60,6 +60,9 @@ class GEventWorker(AsyncWorker): conn, addr, gt = None, None, None except greenlet.GreenletExit: return + except: + self.log.exception("Unexpected error in acceptor. Sepuku.") + os._exit(4) def cleanup(self, gt): try: