summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Shepelev <temotor@gmail.com>2016-06-01 21:28:02 +0500
committerSergey Shepelev <temotor@gmail.com>2016-06-01 21:28:02 +0500
commit4b54ca96665aff3eb9b3efa09b4bebc51c65913f (patch)
tree53701584ced2dba5159ecbc33b88113d544893c5
parent41bbe278d6ab1eaf52e4d7af3a01a4053fc6e2b1 (diff)
downloadeventlet-issue-320.tar.gz
wsgi: chunked timeout should close connection immediatelyissue-320
-rw-r--r--eventlet/wsgi.py7
-rw-r--r--tests/__init__.py9
-rw-r--r--tests/wsgi_test.py24
-rw-r--r--tox.ini1
4 files changed, 41 insertions, 0 deletions
diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py
index 9d02d12..4ca6ac9 100644
--- a/eventlet/wsgi.py
+++ b/eventlet/wsgi.py
@@ -319,6 +319,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
"of type %s" % type(conn))
def handle_one_request(self):
+ print('wsgi: socket: {0}'.format(repr(self.connection.fileno())))
if self.server.max_http_version:
self.protocol_version = self.server.max_http_version
@@ -630,10 +631,15 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
try:
BaseHTTPServer.BaseHTTPRequestHandler.finish(self)
except socket.error as e:
+ print('wsgi.finish error:', str(e))
# Broken pipe, connection reset by peer
if support.get_errno(e) not in BROKEN_SOCK:
raise
+ # finally:
+ # pass
+ print('wsgi.finish shutdown')
greenio.shutdown_safe(self.connection)
+ print('wsgi.finish close')
self.connection.close()
def handle_expect_100(self):
@@ -718,6 +724,7 @@ class Server(BaseHTTPServer.HTTPServer):
try:
proto.__init__(sock, address, self)
except socket.timeout:
+ print('socket.timeout')
# Expected exceptions are not exceptional
sock.close()
# similar to logging "accepted" in server()
diff --git a/tests/__init__.py b/tests/__init__.py
index 62bae83..3665811 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -21,6 +21,7 @@ import unittest
import warnings
from nose.plugins.skip import SkipTest
+import psutil
import eventlet
from eventlet import tpool
@@ -346,5 +347,13 @@ def run_isolated(path, prefix='tests/isolated/', env=None, args=None):
assert ok, 'Expected single line "pass" in stdout'
+def get_sockets(filters=None):
+ xs = psutil.Process().connections(kind='all')
+ print('get_sockets: {0}'.format(xs))
+ if filters:
+ xs = [c for c in xs if all(getattr(c, f) == filters[f] for f in filters)]
+ return xs
+
+
certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py
index 3d2f11f..f6d9935 100644
--- a/tests/wsgi_test.py
+++ b/tests/wsgi_test.py
@@ -1527,6 +1527,30 @@ class TestHttpd(_TestBase):
assert result.status == 'HTTP/1.1 200 OK'
assert result.body == b'Host: localhost\nx-ANY_k: one\nx-ANY_k: two'
+ def test_chunked_timeout(self):
+ def app(env, start_response):
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ line = b'a' * (1 << 20)
+ for _ in range(10):
+ yield line
+ eventlet.sleep(0.1)
+
+ self.spawn_server(site=app, socket_timeout=0.1)
+ sock = eventlet.connect(self.server_addr)
+ print('client socket: {0}'.format(sock.fileno()))
+ sock.sendall(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
+ status, headers = read_headers(sock)
+ assert headers['transfer-encoding'] == 'chunked'
+ ss = tests.get_sockets(filters={'status': 'ESTABLISHED'})
+ assert len(ss) == 2, repr(ss)
+
+ sock.recv(1)
+ eventlet.sleep(0.2)
+ recvall(sock)
+ ss = tests.get_sockets(filters={'status': 'ESTABLISHED'})
+ assert len(ss) == 0, repr(ss)
+ sock.close()
+
def read_headers(sock):
fd = sock.makefile('rb')
diff --git a/tox.ini b/tox.ini
index 2d14401..58258a7 100644
--- a/tox.ini
+++ b/tox.ini
@@ -43,6 +43,7 @@ basepython =
pypy: pypy
deps =
nose==1.3.1
+ psutil==4.2.0
setuptools==5.4.1
py{26,27}: subprocess32==3.2.7
py27-dns: dnspython==1.12.0