diff --git a/lib/_emerge/EbuildPhase.py b/lib/_emerge/EbuildPhase.py index 234a273a09..63d0746da3 100644 --- a/lib/_emerge/EbuildPhase.py +++ b/lib/_emerge/EbuildPhase.py @@ -23,7 +23,7 @@ ) 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 @@ def _start(self): 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 80908936c7..a4555275f0 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 @@ def schedule(self): 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()