Use async_unlock to avoid event loop recursion, and AsyncTaskFuture
to fit the resulting future into the CompositeTask framework that
EbuildPhase uses.

Bug: https://bugs.gentoo.org/614108
---
 pym/_emerge/EbuildPhase.py | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py
index 3174cac1a..890b17870 100644
--- a/pym/_emerge/EbuildPhase.py
+++ b/pym/_emerge/EbuildPhase.py
@@ -1,6 +1,7 @@
 # Copyright 1999-2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
+import functools
 import gzip
 import io
 import sys
@@ -15,6 +16,7 @@ from _emerge.PackagePhase import PackagePhase
 from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir,
                _prepare_fake_distdir, _prepare_fake_filesdir)
 from portage.util import writemsg
+from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
 
 try:
        from portage.xml.metadata import MetaDataXML
@@ -197,13 +199,23 @@ class EbuildPhase(CompositeTask):
                self._start_task(ebuild_process, self._ebuild_exit)
 
        def _ebuild_exit(self, ebuild_process):
-
-               if self._ebuild_lock is not None:
-                       self._ebuild_lock.unlock()
-                       self._ebuild_lock = None
+               self._assert_current(ebuild_process)
+               if self._ebuild_lock is None:
+                       self._ebuild_exit_unlocked(ebuild_process)
+               else:
+                       self._start_task(
+                               
AsyncTaskFuture(future=self._ebuild_lock.async_unlock()),
+                               functools.partial(self._ebuild_exit_unlocked, 
ebuild_process))
+
+       def _ebuild_exit_unlocked(self, ebuild_process, unlock_task=None):
+               if unlock_task is not None:
+                       self._assert_current(unlock_task)
+                       # Normally, async_unlock should not raise an exception 
here.
+                       unlock_task.future.result()
 
                fail = False
-               if self._default_exit(ebuild_process) != os.EX_OK:
+               if ebuild_process.returncode != os.EX_OK:
+                       self.returncode = ebuild_process.returncode
                        if self.phase == "test" and \
                                "test-fail-continue" in self.settings.features:
                                # mark test phase as complete (bug #452030)
-- 
2.13.6


Reply via email to