Skip to content

Commit

Permalink
EbuildPhase: add _async_start coroutine
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
zmedico committed Feb 18, 2020
1 parent a287c49 commit c7e52d0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
21 changes: 11 additions & 10 deletions lib/_emerge/EbuildPhase.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
20 changes: 16 additions & 4 deletions lib/_emerge/SequentialTaskQueue.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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()

Expand Down

0 comments on commit c7e52d0

Please sign in to comment.