1 |
commit: c7e52d0466211907d20cdbc04f1e90e7da626694 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Feb 17 23:39:12 2020 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Feb 18 00:14:00 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=c7e52d04 |
7 |
|
8 |
EbuildPhase: add _async_start coroutine |
9 |
|
10 |
Convert the _start method to an _async_start coroutine, since |
11 |
eventually this method will need to be a coroutine in order to write |
12 |
messages to the build log as discussed in bug 709746. |
13 |
|
14 |
Also convert SequentialTaskQueue to use the async_start method, |
15 |
which is now required in order to start EbuildPhase instances. |
16 |
|
17 |
Bug: https://bugs.gentoo.org/709746 |
18 |
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> |
19 |
|
20 |
lib/_emerge/EbuildPhase.py | 21 +++++++++++---------- |
21 |
lib/_emerge/SequentialTaskQueue.py | 20 ++++++++++++++++---- |
22 |
2 files changed, 27 insertions(+), 14 deletions(-) |
23 |
|
24 |
diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py |
25 |
index 234a273a0..63d0746da 100644 |
26 |
--- a/lib/_emerge/EbuildPhase.py |
27 |
+++ b/lib/_emerge/EbuildPhase.py |
28 |
@@ -23,7 +23,7 @@ from portage.util._dyn_libs.soname_deps_qa import ( |
29 |
) |
30 |
from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir, |
31 |
_prepare_fake_distdir, _prepare_fake_filesdir) |
32 |
-from portage.util.futures.compat_coroutine import coroutine |
33 |
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return |
34 |
from portage.util import writemsg |
35 |
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture |
36 |
from portage.util.futures.executor.fork import ForkExecutor |
37 |
@@ -69,6 +69,10 @@ class EbuildPhase(CompositeTask): |
38 |
_locked_phases = ("setup", "preinst", "postinst", "prerm", "postrm") |
39 |
|
40 |
def _start(self): |
41 |
+ self.scheduler.run_until_complete(self._async_start()) |
42 |
+ |
43 |
+ @coroutine |
44 |
+ def _async_start(self): |
45 |
|
46 |
need_builddir = self.phase not in EbuildProcess._phases_without_builddir |
47 |
|
48 |
@@ -138,20 +142,17 @@ class EbuildPhase(CompositeTask): |
49 |
env_extractor = BinpkgEnvExtractor(background=self.background, |
50 |
scheduler=self.scheduler, settings=self.settings) |
51 |
if env_extractor.saved_env_exists(): |
52 |
- self._start_task(env_extractor, self._env_extractor_exit) |
53 |
- return |
54 |
+ self._current_task = env_extractor |
55 |
+ yield env_extractor.async_start() |
56 |
+ yield env_extractor.async_wait() |
57 |
+ if self._default_exit(env_extractor) != os.EX_OK: |
58 |
+ self._async_wait() |
59 |
+ coroutine_return() |
60 |
# If the environment.bz2 doesn't exist, then ebuild.sh will |
61 |
# source the ebuild as a fallback. |
62 |
|
63 |
self._start_lock() |
64 |
|
65 |
- def _env_extractor_exit(self, env_extractor): |
66 |
- if self._default_exit(env_extractor) != os.EX_OK: |
67 |
- self.wait() |
68 |
- return |
69 |
- |
70 |
- self._start_lock() |
71 |
- |
72 |
def _start_lock(self): |
73 |
if (self.phase in self._locked_phases and |
74 |
"ebuild-locks" in self.settings.features): |
75 |
|
76 |
diff --git a/lib/_emerge/SequentialTaskQueue.py b/lib/_emerge/SequentialTaskQueue.py |
77 |
index 80908936c..a4555275f 100644 |
78 |
--- a/lib/_emerge/SequentialTaskQueue.py |
79 |
+++ b/lib/_emerge/SequentialTaskQueue.py |
80 |
@@ -1,9 +1,12 @@ |
81 |
-# Copyright 1999-2012 Gentoo Foundation |
82 |
+# Copyright 1999-2020 Gentoo Authors |
83 |
# Distributed under the terms of the GNU General Public License v2 |
84 |
|
85 |
from collections import deque |
86 |
+import functools |
87 |
import sys |
88 |
|
89 |
+from portage.util.futures import asyncio |
90 |
+from portage.util.futures.compat_coroutine import coroutine |
91 |
from portage.util.SlotObject import SlotObject |
92 |
|
93 |
class SequentialTaskQueue(SlotObject): |
94 |
@@ -41,18 +44,27 @@ class SequentialTaskQueue(SlotObject): |
95 |
cancelled = getattr(task, "cancelled", None) |
96 |
if not cancelled: |
97 |
self.running_tasks.add(task) |
98 |
- task.addExitListener(self._task_exit) |
99 |
- task.start() |
100 |
+ future = asyncio.ensure_future(self._task_coroutine(task), loop=task.scheduler) |
101 |
+ future.add_done_callback(functools.partial(self._task_exit, task)) |
102 |
finally: |
103 |
self._scheduling = False |
104 |
|
105 |
- def _task_exit(self, task): |
106 |
+ @coroutine |
107 |
+ def _task_coroutine(self, task): |
108 |
+ yield task.async_start() |
109 |
+ yield task.async_wait() |
110 |
+ |
111 |
+ def _task_exit(self, task, future): |
112 |
""" |
113 |
Since we can always rely on exit listeners being called, the set of |
114 |
running tasks is always pruned automatically and there is never any need |
115 |
to actively prune it. |
116 |
""" |
117 |
self.running_tasks.remove(task) |
118 |
+ try: |
119 |
+ future.result() |
120 |
+ except asyncio.CancelledError: |
121 |
+ self.clear() |
122 |
if self._task_queue: |
123 |
self.schedule() |