@@ -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'
0 commit comments