Gentoo Archives: gentoo-commits

From: Brian Dolbec <dolsen@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:repoman commit in: pym/portage/util/_eventloop/
Date: Tue, 27 Jun 2017 20:06:09
Message-Id: 1494009165.dac5089eb7908e9fd643f46c913515082077281e.dolsen@gentoo
1 commit: dac5089eb7908e9fd643f46c913515082077281e
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Fri May 5 09:07:38 2017 +0000
4 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
5 CommitDate: Fri May 5 18:32:45 2017 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=dac5089e
7
8 Eventloop: fix deadlock involving idle_add/call_soon (bug 617550)
9
10 Guarantee that newly added idle_add/call_soon callbacks have an
11 opportunity to execute before the event loop decides to wait on
12 self._thread_condition without a timeout. This fixes a case where
13 the event loop would wait on self._thread_condition indefinitely,
14 even though a callback scheduled by the AsynchronousTask._async_wait
15 method needed to be executed first.
16
17 X-Gentoo-bug: 617550
18 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=617550
19 Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>
20
21 pym/portage/util/_eventloop/EventLoop.py | 18 ++++++++++++++++--
22 1 file changed, 16 insertions(+), 2 deletions(-)
23
24 diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py
25 index 712838e3d..cd154005f 100644
26 --- a/pym/portage/util/_eventloop/EventLoop.py
27 +++ b/pym/portage/util/_eventloop/EventLoop.py
28 @@ -108,6 +108,15 @@ class EventLoop(object):
29 self._poll_event_handler_ids = {}
30 # Increment id for each new handler.
31 self._event_handler_id = 0
32 + # New call_soon callbacks must have an opportunity to
33 + # execute before it's safe to wait on self._thread_condition
34 + # without a timeout, since delaying its execution indefinitely
35 + # could lead to a deadlock. The following attribute stores the
36 + # event handler id of the most recently added call_soon callback.
37 + # If this attribute has changed since the last time that the
38 + # call_soon callbacks have been called, then it's not safe to
39 + # wait on self._thread_condition without a timeout.
40 + self._call_soon_id = 0
41 # Use OrderedDict in order to emulate the FIFO queue behavior
42 # of the AbstractEventLoop.call_soon method.
43 self._idle_callbacks = OrderedDict()
44 @@ -250,10 +259,15 @@ class EventLoop(object):
45
46 if not event_handlers:
47 with self._thread_condition:
48 + prev_call_soon_id = self._call_soon_id
49 if self._run_timeouts():
50 events_handled += 1
51 timeouts_checked = True
52 - if not event_handlers and not events_handled and may_block:
53 +
54 + call_soon = prev_call_soon_id != self._call_soon_id
55 +
56 + if (not call_soon and not event_handlers
57 + and not events_handled and may_block):
58 # Block so that we don't waste cpu time by looping too
59 # quickly. This makes EventLoop useful for code that needs
60 # to wait for timeout callbacks regardless of whether or
61 @@ -457,7 +471,7 @@ class EventLoop(object):
62 @return: an integer ID
63 """
64 with self._thread_condition:
65 - source_id = self._new_source_id()
66 + source_id = self._call_soon_id = self._new_source_id()
67 self._idle_callbacks[source_id] = self._idle_callback_class(
68 args=args, callback=callback, source_id=source_id)
69 self._thread_condition.notify()