aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2020-02-17 15:39:12 -0800
committerZac Medico <zmedico@gentoo.org>2020-02-17 16:14:00 -0800
commitc7e52d0466211907d20cdbc04f1e90e7da626694 (patch)
tree8367cb70d34d7aeee55e528870ceb5108504d6b5 /lib/_emerge
parentAbstractEbuildProcess: add _async_start coroutine (diff)
downloadportage-c7e52d0466211907d20cdbc04f1e90e7da626694.tar.gz
portage-c7e52d0466211907d20cdbc04f1e90e7da626694.tar.bz2
portage-c7e52d0466211907d20cdbc04f1e90e7da626694.zip
EbuildPhase: add _async_start coroutine
Convert the _start method to an _async_start coroutine, since eventually this method will need to be a coroutine in order to write messages to the build log as discussed in bug 709746. Also convert SequentialTaskQueue to use the async_start method, which is now required in order to start EbuildPhase instances. Bug: https://bugs.gentoo.org/709746 Signed-off-by: Zac Medico <zmedico@gentoo.org>
Diffstat (limited to 'lib/_emerge')
-rw-r--r--lib/_emerge/EbuildPhase.py21
-rw-r--r--lib/_emerge/SequentialTaskQueue.py20
2 files changed, 27 insertions, 14 deletions
diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py
index 234a273a0..63d0746da 100644
--- a/lib/_emerge/EbuildPhase.py
+++ b/lib/_emerge/EbuildPhase.py
@@ -23,7 +23,7 @@ from portage.util._dyn_libs.soname_deps_qa import (
)
from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir,
_prepare_fake_distdir, _prepare_fake_filesdir)
-from portage.util.futures.compat_coroutine import coroutine
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return
from portage.util import writemsg
from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
from portage.util.futures.executor.fork import ForkExecutor
@@ -69,6 +69,10 @@ class EbuildPhase(CompositeTask):
_locked_phases = ("setup", "preinst", "postinst", "prerm", "postrm")
def _start(self):
+ self.scheduler.run_until_complete(self._async_start())
+
+ @coroutine
+ def _async_start(self):
need_builddir = self.phase not in EbuildProcess._phases_without_builddir
@@ -138,20 +142,17 @@ class EbuildPhase(CompositeTask):
env_extractor = BinpkgEnvExtractor(background=self.background,
scheduler=self.scheduler, settings=self.settings)
if env_extractor.saved_env_exists():
- self._start_task(env_extractor, self._env_extractor_exit)
- return
+ self._current_task = env_extractor
+ yield env_extractor.async_start()
+ yield env_extractor.async_wait()
+ if self._default_exit(env_extractor) != os.EX_OK:
+ self._async_wait()
+ coroutine_return()
# If the environment.bz2 doesn't exist, then ebuild.sh will
# source the ebuild as a fallback.
self._start_lock()
- def _env_extractor_exit(self, env_extractor):
- if self._default_exit(env_extractor) != os.EX_OK:
- self.wait()
- return
-
- self._start_lock()
-
def _start_lock(self):
if (self.phase in self._locked_phases and
"ebuild-locks" in self.settings.features):
diff --git a/lib/_emerge/SequentialTaskQueue.py b/lib/_emerge/SequentialTaskQueue.py
index 80908936c..a4555275f 100644
--- a/lib/_emerge/SequentialTaskQueue.py
+++ b/lib/_emerge/SequentialTaskQueue.py
@@ -1,9 +1,12 @@
-# Copyright 1999-2012 Gentoo Foundation
+# Copyright 1999-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from collections import deque
+import functools
import sys
+from portage.util.futures import asyncio
+from portage.util.futures.compat_coroutine import coroutine
from portage.util.SlotObject import SlotObject
class SequentialTaskQueue(SlotObject):
@@ -41,18 +44,27 @@ class SequentialTaskQueue(SlotObject):
cancelled = getattr(task, "cancelled", None)
if not cancelled:
self.running_tasks.add(task)
- task.addExitListener(self._task_exit)
- task.start()
+ future = asyncio.ensure_future(self._task_coroutine(task), loop=task.scheduler)
+ future.add_done_callback(functools.partial(self._task_exit, task))
finally:
self._scheduling = False
- def _task_exit(self, task):
+ @coroutine
+ def _task_coroutine(self, task):
+ yield task.async_start()
+ yield task.async_wait()
+
+ def _task_exit(self, task, future):
"""
Since we can always rely on exit listeners being called, the set of
running tasks is always pruned automatically and there is never any need
to actively prune it.
"""
self.running_tasks.remove(task)
+ try:
+ future.result()
+ except asyncio.CancelledError:
+ self.clear()
if self._task_queue:
self.schedule()