Commit 1b429e2a authored by Iustin Pop's avatar Iustin Pop
Browse files

Fix utils.WaitForFdCondition inner retry loop

Commit dfdc4060

 added WaitForFdCondition which uses utils.Retry without
handling timeout exceptions. This breaks any nested retry loops.

This patch fixes the above function, and also changes utils.Retry to
detect and warn future similar cases. In addition, we add a few small
unittests for utils.Retry.
Signed-off-by: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent cc2f004d
......@@ -166,7 +166,8 @@ class AsyncUDPSocket(asyncore.dispatcher):
@return: True if some data has been handled, False otherwise
"""
if utils.WaitForFdCondition(self, select.POLLIN, timeout) & select.POLLIN:
result = utils.WaitForFdCondition(self, select.POLLIN, timeout)
if result is not None and result & select.POLLIN:
self.do_read()
return True
else:
......
......@@ -1579,8 +1579,11 @@ def WaitForFdCondition(fdobj, event, timeout):
"""
if timeout is not None:
retrywaiter = FdConditionWaiterHelper(timeout)
result = Retry(retrywaiter.Poll, RETRY_REMAINING_TIME, timeout,
args=(fdobj, event), wait_fn=retrywaiter.UpdateTimeout)
try:
result = Retry(retrywaiter.Poll, RETRY_REMAINING_TIME, timeout,
args=(fdobj, event), wait_fn=retrywaiter.UpdateTimeout)
except RetryTimeout:
result = None
else:
result = None
while result is None:
......@@ -2606,6 +2609,9 @@ def Retry(fn, delay, timeout, args=None, wait_fn=time.sleep,
return fn(*args)
except RetryAgain:
pass
except RetryTimeout:
raise errors.ProgrammerError("Nested retry loop detected that didn't"
" handle RetryTimeout")
remaining_time = end_time - _time_fn()
......
......@@ -1535,5 +1535,28 @@ class TestMakedirs(unittest.TestCase):
self.assert_(os.path.isdir(path))
class TestRetry(testutils.GanetiTestCase):
@staticmethod
def _RaiseRetryAgain():
raise utils.RetryAgain()
def _WrongNestedLoop(self):
return utils.Retry(self._RaiseRetryAgain, 0.01, 0.02)
def testRaiseTimeout(self):
self.failUnlessRaises(utils.RetryTimeout, utils.Retry,
self._RaiseRetryAgain, 0.01, 0.02)
def testComplete(self):
self.failUnlessEqual(utils.Retry(lambda: True, 0, 1), True)
def testNestedLoop(self):
try:
self.failUnlessRaises(errors.ProgrammerError, utils.Retry,
self._WrongNestedLoop, 0, 1)
except utils.RetryTimeout:
self.fail("Didn't detect inner loop's exception")
if __name__ == '__main__':
testutils.GanetiTestProgram()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment