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()
 

Reply via email to