From 3e08f3375e2a79c04050a562f6588934638c70e9 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Wed, 31 Oct 2018 22:44:23 +0100 Subject: [PATCH] Fix stop of loopingcall Patch [1] for switched to use eventlet Event for loopingcall events. It may now happen that stop event is sent when other event was already sent and loopingcall is already not running. That cause AssertionError in eventlet.event module. To avoid that, we should check if if loopingcall is running before sending _abort.set(). [1] https://review.openstack.org/#/c/611807/ Closes-Bug #1800879 Change-Id: I28ad3bdb51a20350c90dee4420058c30946897e5 --- oslo_service/loopingcall.py | 3 ++- oslo_service/tests/test_loopingcall.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/oslo_service/loopingcall.py b/oslo_service/loopingcall.py index 9e6a8799..dc958040 100644 --- a/oslo_service/loopingcall.py +++ b/oslo_service/loopingcall.py @@ -121,7 +121,8 @@ class LoopingCallBase(object): return not self._abort.is_set() def stop(self): - self._abort.set() + if self._running: + self._abort.set() def wait(self): return self.done.wait() diff --git a/oslo_service/tests/test_loopingcall.py b/oslo_service/tests/test_loopingcall.py index 9ca0afe2..35d05a1a 100644 --- a/oslo_service/tests/test_loopingcall.py +++ b/oslo_service/tests/test_loopingcall.py @@ -100,6 +100,16 @@ class LoopingCallTestCase(test_base.BaseTestCase): wait_ev.set() timer.wait() + def test_no_double_stop(self): + def _raise_it(): + raise loopingcall.LoopingCallDone(False) + + timer = loopingcall.FixedIntervalLoopingCall(_raise_it) + timer.start(interval=0.5) + + timer.stop() + timer.stop() + def test_repeat(self): self.num_runs = 2