From f8b1e84d2ff2dc327427daa91c4b4cc294ac11e2 Mon Sep 17 00:00:00 2001 From: Jordan Pittier Date: Tue, 25 Feb 2020 11:46:56 +0100 Subject: [PATCH] Do not raise and crash worker on ENOTCONN error A couple of socket operations can fail with ENOTCONN error if the other side of the connection is not connected anymore. In that case, let's not crash the whole worker and give a chance to accept new connections. In my case, the operation that sometimes fails is a "getpeername()", which was introduced in b07532be752668be5eb5dbd0a8303abf5c219c99 (v19.8.0). Someone in https://github.com/benoitc/gunicorn/issues/1913 metionned that v19.7.1 was working fine so it matches. Fixes #1913 --- gunicorn/workers/base_async.py | 4 +++- gunicorn/workers/gthread.py | 4 +++- gunicorn/workers/sync.py | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/gunicorn/workers/base_async.py b/gunicorn/workers/base_async.py index 7b2daf91..a19cd313 100644 --- a/gunicorn/workers/base_async.py +++ b/gunicorn/workers/base_async.py @@ -73,11 +73,13 @@ class AsyncWorker(base.Worker): self.log.debug("Error processing SSL request.") self.handle_error(req, client, addr, e) except EnvironmentError as e: - if e.errno not in (errno.EPIPE, errno.ECONNRESET): + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): self.log.exception("Socket error processing request.") else: if e.errno == errno.ECONNRESET: self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") else: self.log.debug("Ignoring EPIPE") except Exception as e: diff --git a/gunicorn/workers/gthread.py b/gunicorn/workers/gthread.py index 376c3cb7..adfa7eac 100644 --- a/gunicorn/workers/gthread.py +++ b/gunicorn/workers/gthread.py @@ -285,11 +285,13 @@ class ThreadWorker(base.Worker): self.handle_error(req, conn.sock, conn.client, e) except EnvironmentError as e: - if e.errno not in (errno.EPIPE, errno.ECONNRESET): + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): self.log.exception("Socket error processing request.") else: if e.errno == errno.ECONNRESET: self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") else: self.log.debug("Ignoring connection epipe") except Exception as e: diff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py index fd423bc9..700a1b85 100644 --- a/gunicorn/workers/sync.py +++ b/gunicorn/workers/sync.py @@ -146,11 +146,13 @@ class SyncWorker(base.Worker): self.log.debug("Error processing SSL request.") self.handle_error(req, client, addr, e) except EnvironmentError as e: - if e.errno not in (errno.EPIPE, errno.ECONNRESET): + if e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ENOTCONN): self.log.exception("Socket error processing request.") else: if e.errno == errno.ECONNRESET: self.log.debug("Ignoring connection reset") + elif e.errno == errno.ENOTCONN: + self.log.debug("Ignoring socket not connected") else: self.log.debug("Ignoring EPIPE") except Exception as e: