Close ECAppIter's sub-generators before propagating GeneratorExit

... which ensures no Timeouts remain pending after the parent generator
is closed when a client disconnects before being able to read the entire
body.

Also tighten up a few tests that may have left some open ECAppIter
generators lying about after the tests themselves had finished.  This
has the side effect of preventing the extraneous printing of the Timeout
errors being raised by the eventlet hub in the background while our
unittests are running.

Change-Id: I156d873c72c19623bcfbf39bf120c98800b3cada
This commit is contained in:
Clay Gerrard 2015-10-02 16:40:28 -07:00
parent 47eb6a37f8
commit 752ceb266b
3 changed files with 9 additions and 7 deletions

View File

@ -917,6 +917,7 @@ class ResumingGetter(object):
if nchunks % 5 == 0:
sleep()
part_iter = None
try:
while True:
start_byte, end_byte, length, headers, part = \
@ -928,9 +929,12 @@ class ResumingGetter(object):
'entity_length': length, 'headers': headers,
'part_iter': part_iter}
self.pop_range()
except GeneratorExit:
if part_iter:
part_iter.close()
raise
except StopIteration:
req.environ['swift.non_client_disconnect'] = True
return
except ChunkReadTimeout:
self.app.exception_occurred(node[0], _('Object'),

View File

@ -2001,7 +2001,7 @@ class TestECObjController(BaseObjectControllerMixin, unittest.TestCase):
try:
resp.body
except ECDriverError:
pass
resp._app_iter.close()
else:
self.fail('invalid ec fragment response body did not blow up!')
error_lines = self.logger.get_lines_for_level('error')

View File

@ -5619,9 +5619,8 @@ class TestObjectController(unittest.TestCase):
# read most of the object, and disconnect
fd.read(10)
fd.close()
sock.close()
sleep(0)
sock.fd._sock.close()
sleep(0.1)
# check for disconnect message!
expected = ['Client disconnected on read'] * 2
@ -5677,8 +5676,7 @@ class TestObjectController(unittest.TestCase):
exp = 'HTTP/1.1 200'
self.assertEqual(headers[:len(exp)], exp)
fd.read(1)
fd.close()
sock.close()
sock.fd._sock.close()
# Make sure the GC is run again for pythons without reference
# counting
for i in range(4):