Gentoo Archives: gentoo-portage-dev

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