From 66c905e29458666cbd3ea6638a6a4c137e6a35a8 Mon Sep 17 00:00:00 2001 From: Timur Alperovich Date: Mon, 29 Aug 2016 17:27:50 -0700 Subject: [PATCH] Close the iterators in string_along. Make sure to close the underlying iterator in string_along. What is currently happening when using the InternalClient is that "Client disconnected" warnings are generated and resources are tied up until GC runs. Change-Id: If1f6c0c756aee95f53f99371439533a97d347eab --- swift/common/utils.py | 5 +++-- test/unit/common/test_utils.py | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/swift/common/utils.py b/swift/common/utils.py index 57e0e9be3f..eaec22f86c 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -3757,8 +3757,9 @@ def document_iters_to_http_response_body(ranges_iter, boundary, multipart, # so if that finally block fires before we read response_body_iter, # there's nothing there. def string_along(useful_iter, useless_iter_iter, logger): - for x in useful_iter: - yield x + with closing_if_possible(useful_iter): + for x in useful_iter: + yield x try: next(useless_iter_iter) diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 707a293d6e..4cdede7574 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -5637,6 +5637,28 @@ class TestDocumentItersToHTTPResponseBody(unittest.TestCase): part2 + "\r\n" + "--boundaryboundary--")) + def test_closed_part_iterator(self): + print('test') + useful_iter_mock = mock.MagicMock() + useful_iter_mock.__iter__.return_value = [''] + body_iter = utils.document_iters_to_http_response_body( + iter([{'part_iter': useful_iter_mock}]), 'dontcare', + multipart=False, logger=FakeLogger()) + body = '' + for s in body_iter: + body += s + self.assertEqual(body, '') + useful_iter_mock.close.assert_called_once_with() + + # Calling "close" on the mock will now raise an AttributeError + del useful_iter_mock.close + body_iter = utils.document_iters_to_http_response_body( + iter([{'part_iter': useful_iter_mock}]), 'dontcare', + multipart=False, logger=FakeLogger()) + body = '' + for s in body_iter: + body += s + class TestPairs(unittest.TestCase): def test_pairs(self):