X Tutup
Skip to content

Commit 2205da4

Browse files
Issue #21032. Fixed socket leak if HTTPConnection.getresponse() fails.
Original patch by Martin Panter.
2 parents 988e2cf + b491e05 commit 2205da4

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

Lib/http/client.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,18 +1233,22 @@ class the response_class variable.
12331233
else:
12341234
response = self.response_class(self.sock, method=self._method)
12351235

1236-
response.begin()
1237-
assert response.will_close != _UNKNOWN
1238-
self.__state = _CS_IDLE
1236+
try:
1237+
response.begin()
1238+
assert response.will_close != _UNKNOWN
1239+
self.__state = _CS_IDLE
12391240

1240-
if response.will_close:
1241-
# this effectively passes the connection to the response
1242-
self.close()
1243-
else:
1244-
# remember this, so we can tell when it is complete
1245-
self.__response = response
1241+
if response.will_close:
1242+
# this effectively passes the connection to the response
1243+
self.close()
1244+
else:
1245+
# remember this, so we can tell when it is complete
1246+
self.__response = response
12461247

1247-
return response
1248+
return response
1249+
except:
1250+
response.close()
1251+
raise
12481252

12491253
try:
12501254
import ssl

Lib/test/test_httplib.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def __init__(self, text, fileclass=io.BytesIO, host=None, port=None):
4848
self.fileclass = fileclass
4949
self.data = b''
5050
self.sendall_calls = 0
51+
self.file_closed = False
5152
self.host = host
5253
self.port = port
5354

@@ -60,9 +61,12 @@ def makefile(self, mode, bufsize=None):
6061
raise client.UnimplementedFileMode()
6162
# keep the file around so we can check how much was read from it
6263
self.file = self.fileclass(self.text)
63-
self.file.close = lambda:None #nerf close ()
64+
self.file.close = self.file_close #nerf close ()
6465
return self.file
6566

67+
def file_close(self):
68+
self.file_closed = True
69+
6670
def close(self):
6771
pass
6872

@@ -676,6 +680,22 @@ def test_delayed_ack_opt(self):
676680
conn.request('POST', '/', body)
677681
self.assertGreater(sock.sendall_calls, 1)
678682

683+
def test_error_leak(self):
684+
# Test that the socket is not leaked if getresponse() fails
685+
conn = client.HTTPConnection('example.com')
686+
response = None
687+
class Response(client.HTTPResponse):
688+
def __init__(self, *pos, **kw):
689+
nonlocal response
690+
response = self # Avoid garbage collector closing the socket
691+
client.HTTPResponse.__init__(self, *pos, **kw)
692+
conn.response_class = Response
693+
conn.sock = FakeSocket('') # Emulate server dropping connection
694+
conn.request('GET', '/')
695+
self.assertRaises(client.BadStatusLine, conn.getresponse)
696+
self.assertTrue(response.closed)
697+
self.assertTrue(conn.sock.file_closed)
698+
679699
def test_chunked_extension(self):
680700
extra = '3;foo=bar\r\n' + 'abc\r\n'
681701
expected = chunked_expected + b'abc'

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ Core and Builtins
191191
Library
192192
-------
193193

194+
- Issue #21032. Fixed socket leak if HTTPConnection.getresponse() fails.
195+
Original patch by Martin Panter.
196+
194197
- Issue #22407: Deprecated the use of re.LOCALE flag with str patterns or
195198
re.ASCII. It was newer worked.
196199

0 commit comments

Comments
 (0)
X Tutup