commit:     d36f8b2c9c43311f4c1333afe7ce1cc7a147b836
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Tue Apr 17 18:19:02 2018 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Tue Apr 17 18:19:02 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=d36f8b2c

EventLoop._run_idle_callbacks: make recursive calls fatal

The caller should use call_soon in order to prevent recursion
here. Raise an error because _run_idle_callbacks has an internal
remaining count that recursion would render meaningless.

Fixes: 9772f8f2a58a (EventLoop._idle_add: use thread-safe deque append)

 pym/portage/util/_eventloop/EventLoop.py | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/pym/portage/util/_eventloop/EventLoop.py 
b/pym/portage/util/_eventloop/EventLoop.py
index a61a3d74a..895303699 100644
--- a/pym/portage/util/_eventloop/EventLoop.py
+++ b/pym/portage/util/_eventloop/EventLoop.py
@@ -145,6 +145,7 @@ class EventLoop(object):
                # Use deque, with thread-safe append, in order to emulate the 
FIFO
                # queue behavior of the AbstractEventLoop.call_soon method.
                self._idle_callbacks = collections.deque()
+               self._idle_callbacks_running = False
                self._timeout_handlers = {}
                self._timeout_interval = None
                self._default_executor = None
@@ -586,8 +587,19 @@ class EventLoop(object):
 
                with self._thread_rlock:
 
-                       if self._run_idle_callbacks():
-                               calls += 1
+                       if self._idle_callbacks_running:
+                               # The caller should use call_soon in order to
+                               # prevent recursion here. Raise an error because
+                               # _run_idle_callbacks has an internal remaining
+                               # count that recursion would render meaningless.
+                               raise AssertionError('idle callback recursion')
+
+                       self._idle_callbacks_running = True
+                       try:
+                               if self._run_idle_callbacks():
+                                       calls += 1
+                       finally:
+                               self._idle_callbacks_running = False
 
                        if not self._timeout_handlers:
                                return bool(calls)

Reply via email to