8000 Merge pull request #734 from Lukasa/defensively_close_connections · python-telegram-bot/urllib3@c948bc3 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on May 21, 2023. It is now read-only.

Commit c948bc3

Browse files
committed
Merge pull request urllib3#734 from Lukasa/defensively_close_connections
Defensively close connections.
2 parents 267a865 + a2b5977 commit c948bc3

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

CONTRIBUTORS.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,5 +181,8 @@ In chronological order:
181181
* John Vandenberg <jayvdb@gmail.com>
182182
* Python 2.6 fixes; pyflakes and pep8 compliance
183183

184+
* Andy Caldwell <andy.m.caldwell@googlemail.com>
185+
* Bugfix related to reusing connections in indeterminate states.
186+
184187
* [Your name or handle] <[email or website]>
185188
* [Brief summary of your changes]

test/with_dummyserver/test_socketlevel.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
class MimeToolMessage(object):
3131
pass
3232
from threading import Event
33+
import select
3334
import socket
3435
import ssl
3536

@@ -366,6 +367,72 @@ def socket_handler(listener):
366367
self.assertRaises(ProtocolError, response.read)
367368
self.assertEqual(poolsize, pool.pool.qsize())
368369

370+
def test_connection_closed_on_read_timeout_preload_false(self):
371+
timed_out = Event()
372+
373+
def socket_handler(listener):
374+
sock = listener.accept()[0]
375+
376+
# Consume request
377+
buf = b''
378+
while not buf.endswith(b'\r\n\r\n'):
379+
buf = sock.recv(65535)
380+
381+
# Send partial chunked response and then hang.
382+
sock.send((
383+
'HTTP/1.1 200 OK\r\n'
384+
'Content-Type: text/plain\r\n'
385+
'Transfer-Encoding: chunked\r\n'
386+
'\r\n'
387+
'8\r\n'
388+
'12345678\r\n').encode('utf-8')
389+
)
390+
timed_out.wait(5)
391+
392+
# Expect a new request, but keep hold of the old socket to avoid
393+
# leaking it. Because we don't want to hang this thread, we
394+
# actually use select.select to confirm that a new request is
395+
# coming in: this lets us time the thread out.
396+
rlist, _, _ = select.select([listener], [], [], 1)
397+
assert rlist
398+
new_sock = listener.accept()[0]
399+
400+
# Consume request
401+
buf = b''
402+
while not buf.endswith(b'\r\n\r\n'):
403+
buf = new_sock.recv(65535)
404+
405+
# Send complete chunked response.
406+
new_sock.send((
407+
'HTTP/1.1 200 OK\r\n'
408+
'Content-Type: text/plain\r\n'
409+
'Transfer-Encoding: chunked\r\n'
410+
'\r\n'
411+
'8\r\n'
412+
'12345678\r\n'
413+
'0\r\n\r\n').encode('utf-8')
414+
)
415+
416+
new_sock.close()
417+
sock.close()
418+
419+
self._start_server(socket_handler)
420+
with HTTPConnectionPool(self.host, self.port) as pool:
421+
# First request should fail.
422+
response = pool.urlopen('GET', '/', retries=0,
423+
preload_content=False,
424+
timeout=Timeout(connect=1, read=0.001))
425+
try:
426+
self.assertRaises(ReadTimeoutError, response.read)
427+
finally:
428+
timed_out.set()
429+
430+
# Second should succeed.
431+
response = pool.urlopen('GET', '/', retries=0,
432+
preload_content=False,
433+
timeout=Timeout(connect=1, read=0.1))
434+
self.assertEqual(len(response.read()), 8)
435+
369436

370437
class TestProxyManager(SocketDummyServerTestCase):
371438

urllib3/response.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ def _error_catcher(self):
236236
if self._original_response and not self._original_response.isclosed():
237237
self._original_response.close()
238238

239+
# Closing the response may not actually be sufficient to close
240+
# everything, so if we have a hold of the connection close that
241+
# too.
242+
if self._connection is not None:
243+
self._connection.close()
244+
239245
raise
240246
finally:
241247
if self._original_response and self._original_response.isclosed():

0 commit comments

Comments
 (0)
0