From aa22115cfc9c2b76c818ce231089b01c690052b6 Mon Sep 17 00:00:00 2001 From: Konstantin Kapustin Date: Fri, 7 Sep 2012 17:08:28 +0400 Subject: [PATCH] Set timeout for client socket (slow client DoS). --- gunicorn/workers/async.py | 5 +++++ gunicorn/workers/base.py | 5 +++++ gunicorn/workers/sync.py | 3 +++ 3 files changed, 13 insertions(+) diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py index 4258d74b..65b16981 100644 --- a/gunicorn/workers/async.py +++ b/gunicorn/workers/async.py @@ -28,6 +28,7 @@ class AsyncWorker(base.Worker): def handle(self, client, addr): req = None try: + client.settimeout(self.cfg.timeout) parser = http.RequestParser(self.cfg, client) try: if not self.cfg.keepalive: @@ -46,8 +47,12 @@ class AsyncWorker(base.Worker): self.log.debug("Ignored premature client disconnection. %s", e) except StopIteration, e: self.log.debug("Closing connection. %s", e) + except socket.error: + raise # pass to next try-except level except Exception, e: self.handle_error(req, client, addr, e) + except socket.timeout as e: + self.handle_error(req, client, addr, e) except socket.error, e: if e[0] not in (errno.EPIPE, errno.ECONNRESET): self.log.exception("Socket error processing request.") diff --git a/gunicorn/workers/base.py b/gunicorn/workers/base.py index 2392e8dd..cb854be0 100644 --- a/gunicorn/workers/base.py +++ b/gunicorn/workers/base.py @@ -8,6 +8,7 @@ import os import signal import sys import traceback +import socket from gunicorn import util @@ -155,6 +156,10 @@ class Worker(object): error=str(exc), ) ) + elif isinstance(exc, socket.timeout): + status_int = 408 + reason = "Request Timeout" + mesg = "

The server timed out handling for the request

" else: self.log.exception("Error handling request") diff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py index 4337de18..baaa8952 100644 --- a/gunicorn/workers/sync.py +++ b/gunicorn/workers/sync.py @@ -67,6 +67,7 @@ class SyncWorker(base.Worker): def handle(self, client, addr): req = None try: + client.settimeout(self.cfg.timeout) parser = http.RequestParser(self.cfg, client) req = parser.next() self.handle_request(req, client, addr) @@ -74,6 +75,8 @@ class SyncWorker(base.Worker): self.log.debug("Ignored premature client disconnection. %s", e) except StopIteration, e: self.log.debug("Closing connection. %s", e) + except socket.timeout as e: + self.handle_error(req, client, addr, e) except socket.error, e: if e[0] != errno.EPIPE: self.log.exception("Error processing request.")