commit: c7e52d0466211907d20cdbc04f1e90e7da626694 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Mon Feb 17 23:39:12 2020 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Tue Feb 18 00:14:00 2020 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=c7e52d04
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 <AT> gentoo.org> lib/_emerge/EbuildPhase.py | 21 +++++++++++---------- lib/_emerge/SequentialTaskQueue.py | 20 ++++++++++++++++---- 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()