Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/
Date: Sun, 29 Apr 2018 04:38:24
Message-Id: 1524975716.bca4f6a58512471cdf1caf644cee9858ca3bd1eb.zmedico@gentoo
1 commit: bca4f6a58512471cdf1caf644cee9858ca3bd1eb
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Thu Apr 26 09:51:43 2018 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sun Apr 29 04:21:56 2018 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=bca4f6a5
7
8 AsynchronousTask: disable event loop recursion (bug 653856)
9
10 Make the wait() and _async_wait() methods raise InvalidStateError
11 when the event loop is running and the returncode is not available,
12 since these cases would trigger event loop recursion. There are no
13 known remaining cases that cause event loop recursion via wait()
14 and _async_wait(), and this patch protects against changes that would
15 accidentally re-introduce event loop recursion.
16
17 Since the wait() method now raises InvalidStateError in cases where
18 it previously would have called the _wait() method, this patch makes
19 it possible to remove the _wait() method implementations from all
20 subclasses of AsynchronousTask. Subclasses that used the _wait()
21 method to perform cleanup now use the _async_wait() method instead.
22
23 Bug: https://bugs.gentoo.org/653856
24
25 pym/_emerge/AbstractEbuildProcess.py | 5 ++++-
26 pym/_emerge/AsynchronousTask.py | 24 ++++++++++++++----------
27 2 files changed, 18 insertions(+), 11 deletions(-)
28
29 diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py
30 index 1012ce166..b10aa4bfa 100644
31 --- a/pym/_emerge/AbstractEbuildProcess.py
32 +++ b/pym/_emerge/AbstractEbuildProcess.py
33 @@ -1,4 +1,4 @@
34 -# Copyright 1999-2012 Gentoo Foundation
35 +# Copyright 1999-2018 Gentoo Foundation
36 # Distributed under the terms of the GNU General Public License v2
37
38 import errno
39 @@ -18,6 +18,7 @@ from portage.localization import _
40 from portage.package.ebuild._ipc.ExitCommand import ExitCommand
41 from portage.package.ebuild._ipc.QueryCommand import QueryCommand
42 from portage import shutil, os
43 +from portage.util.futures import asyncio
44 from portage.util._pty import _create_pty_or_pipe
45 from portage.util import apply_secpass_permissions
46
47 @@ -420,6 +421,8 @@ class AbstractEbuildProcess(SpawnProcess):
48 if self._build_dir is None:
49 SpawnProcess._async_wait(self)
50 elif self._build_dir_unlock is None:
51 + if self.returncode is None:
52 + raise asyncio.InvalidStateError('Result is not ready.')
53 self._async_unlock_builddir(returncode=self.returncode)
54
55 def _async_unlock_builddir(self, returncode=None):
56
57 diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py
58 index 9d8df7f5e..246895d71 100644
59 --- a/pym/_emerge/AsynchronousTask.py
60 +++ b/pym/_emerge/AsynchronousTask.py
61 @@ -1,9 +1,10 @@
62 -# Copyright 1999-2012 Gentoo Foundation
63 +# Copyright 1999-2018 Gentoo Foundation
64 # Distributed under the terms of the GNU General Public License v2
65
66 import signal
67
68 from portage import os
69 +from portage.util.futures import asyncio
70 from portage.util.SlotObject import SlotObject
71
72 class AsynchronousTask(SlotObject):
73 @@ -17,8 +18,7 @@ class AsynchronousTask(SlotObject):
74 """
75
76 __slots__ = ("background", "cancelled", "returncode", "scheduler") + \
77 - ("_exit_listeners", "_exit_listener_stack", "_start_listeners",
78 - "_waiting")
79 + ("_exit_listeners", "_exit_listener_stack", "_start_listeners")
80
81 _cancelled_returncode = - signal.SIGINT
82
83 @@ -68,15 +68,19 @@ class AsynchronousTask(SlotObject):
84
85 def wait(self):
86 """
87 - Deprecated. Use async_wait() instead.
88 + Wait for the returncode attribute to become ready, and return
89 + it. If the returncode is not ready and the event loop is already
90 + running, then the async_wait() method should be used instead of
91 + wait(), because wait() will raise asyncio.InvalidStateError in
92 + this case.
93 +
94 + @rtype: int
95 + @returns: the value of self.returncode
96 """
97 if self.returncode is None:
98 - if not self._waiting:
99 - self._waiting = True
100 - try:
101 - self._wait()
102 - finally:
103 - self._waiting = False
104 + if self.scheduler.is_running():
105 + raise asyncio.InvalidStateError('Result is not ready.')
106 + self.scheduler.run_until_complete(self.async_wait())
107 self._wait_hook()
108 return self.returncode