AsynchronousTask: add _async_wait method
authorZac Medico <zmedico@gentoo.org>
Mon, 31 Dec 2012 01:01:59 +0000 (17:01 -0800)
committerZac Medico <zmedico@gentoo.org>
Mon, 31 Dec 2012 01:04:27 +0000 (17:04 -0800)
For cases where _start returns synchronously, this method is a
convenient way to trigger an asynchronous call to self.wait()
(in order to notify exit listeners), avoiding excessive event
loop recursion (or stack overflow) that synchronous calling of
exit listeners can cause.

pym/_emerge/AbstractEbuildProcess.py
pym/_emerge/AsynchronousLock.py
pym/_emerge/AsynchronousTask.py
pym/_emerge/BinpkgFetcher.py
pym/_emerge/BinpkgVerifier.py
pym/_emerge/EbuildBuild.py
pym/_emerge/EbuildFetcher.py
pym/_emerge/EbuildMetadataPhase.py
pym/_emerge/MergeListItem.py
pym/_emerge/PackageUninstall.py
pym/_emerge/SpawnProcess.py

index 597208f5278201285ea90c5a0545d181bc6f0b9b..6d12cd9990124c2487fcee94317807ecd2750d49 100644 (file)
@@ -56,7 +56,7 @@ class AbstractEbuildProcess(SpawnProcess):
                        (self.phase, self.settings['PORTAGE_BUILDDIR'])
                        self._eerror(textwrap.wrap(msg, 72))
                        self._set_returncode((self.pid, 1 << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                if self.background:
index b4de779f97d2b6467b65789e2f203a09448c5b1e..5bb9663a13c80aa338bda7138527ac3443afa88b 100644 (file)
@@ -49,7 +49,7 @@ class AsynchronousLock(AsynchronousTask):
                                pass
                        else:
                                self.returncode = os.EX_OK
-                               self.wait()
+                               self._async_wait()
                                return
 
                if self._force_process or \
index 7a193ce7dd8facd4fdf7286b62fc08e660bf4c0a..b540575d8e25b614d1760b4028e8f9fc4967b89f 100644 (file)
@@ -60,6 +60,20 @@ class AsynchronousTask(SlotObject):
        def _wait(self):
                return self.returncode
 
+       def _async_wait(self):
+               """
+               For cases where _start exits synchronously, this method is a
+               convenient way to trigger an asynchronous call to self.wait()
+               (in order to notify exit listeners), avoiding excessive event
+               loop recursion (or stack overflow) that synchronous calling of
+               exit listeners can cause.
+               """
+               self.scheduler.idle_add(self._async_wait_cb)
+
+       def _async_wait_cb(self):
+               self.wait()
+               return False
+
        def cancel(self):
                """
                Cancel the task, but do not wait for exit status. If asynchronous exit
index 14f2552cb161308944a88534b348aea6558a80ee..099d3c498a7c62277ae0d37e4918b67d48eb5d4a 100644 (file)
@@ -63,7 +63,7 @@ class BinpkgFetcher(SpawnProcess):
                if pretend:
                        portage.writemsg_stdout("\n%s\n" % uri, noiselevel=-1)
                        self._set_returncode((self.pid, os.EX_OK << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                protocol = urllib_parse_urlparse(uri)[0]
index 0052967f6539df25102542da038b74b8bccf7b68..fd4f266a186e5fac1be458f8da1101c3f091dccc 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1999-2011 Gentoo Foundation
+# Copyright 1999-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.AsynchronousTask import AsynchronousTask
@@ -71,5 +71,4 @@ class BinpkgVerifier(AsynchronousTask):
                                background=self.background)
 
                self.returncode = rval
-               self.wait()
-
+               self._async_wait()
index cec63d992b841a44dae1c80fce1fc81e77bc774a..599875a320a8715f5994ac76f191f7e361083407 100644 (file)
@@ -35,7 +35,7 @@ class EbuildBuild(CompositeTask):
                        if rval != os.EX_OK:
                                self.returncode = rval
                                self._current_task = None
-                               self.wait()
+                               self._async_wait()
                                return
 
                root_config = pkg.root_config
@@ -60,7 +60,7 @@ class EbuildBuild(CompositeTask):
                if not self._check_manifest():
                        self.returncode = 1
                        self._current_task = None
-                       self.wait()
+                       self._async_wait()
                        return
 
                prefetcher = self.prefetcher
index 3cbe1b899355a67a3a663e6cee887172b259e5a0..df790b0d3681ab18cdb6ee16291a17001d1fd831 100644 (file)
@@ -117,13 +117,13 @@ class EbuildFetcher(ForkProcess):
                        msg_lines.append(msg)
                        self._eerror(msg_lines)
                        self._set_returncode((self.pid, 1 << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                if not uri_map:
                        # Nothing to fetch.
                        self._set_returncode((self.pid, os.EX_OK << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                settings = self.config_pool.allocate()
@@ -135,7 +135,7 @@ class EbuildFetcher(ForkProcess):
                        self._prefetch_size_ok(uri_map, settings, ebuild_path):
                        self.config_pool.deallocate(settings)
                        self._set_returncode((self.pid, os.EX_OK << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                nocolor = settings.get("NOCOLOR")
index cc8d77593d298c19f69514c94098f8f12dafc0d2..89734e045331b7e9988f30670ba1db336a360439 100644 (file)
@@ -51,14 +51,14 @@ class EbuildMetadataPhase(SubProcess):
                        # An empty EAPI setting is invalid.
                        self._eapi_invalid(None)
                        self._set_returncode((self.pid, 1 << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                self.eapi_supported = portage.eapi_is_supported(parsed_eapi)
                if not self.eapi_supported:
                        self.metadata = {"EAPI": parsed_eapi}
                        self._set_returncode((self.pid, os.EX_OK << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                settings = self.settings
@@ -114,7 +114,7 @@ class EbuildMetadataPhase(SubProcess):
                        # doebuild failed before spawning
                        self._unregister()
                        self._set_returncode((self.pid, retval << 8))
-                       self.wait()
+                       self._async_wait()
                        return
 
                self.pid = retval[0]
index 371e2e2e24a1a7cbde85899dda7608d65f2d239f..172dfccdf58d5a360a3d66fc3558e2a6a2b21f08 100644 (file)
@@ -32,7 +32,7 @@ class MergeListItem(CompositeTask):
                if pkg.installed:
                        # uninstall,  executed by self.merge()
                        self.returncode = os.EX_OK
-                       self.wait()
+                       self._async_wait()
                        return
 
                args_set = self.args_set
index eb6a947a5272a1d13945a0841adf429b82e2f7c1..16c2f749b3192c409997eaeda377ba54dd1c22f5 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1999-2011 Gentoo Foundation
+# Copyright 1999-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 import logging
@@ -33,7 +33,7 @@ class PackageUninstall(CompositeTask):
                        # Apparently the package got uninstalled
                        # already, so we can safely return early.
                        self.returncode = os.EX_OK
-                       self.wait()
+                       self._async_wait()
                        return
 
                self.settings.setcpv(self.pkg)
@@ -67,7 +67,7 @@ class PackageUninstall(CompositeTask):
                if retval != os.EX_OK:
                        self._builddir_lock.unlock()
                        self.returncode = retval
-                       self.wait()
+                       self._async_wait()
                        return
 
                self._writemsg_level(">>> Unmerging %s...\n" % (self.pkg.cpv,),
index 45d7095178ec964ca3a515cb0caf6e6a99aae51d..2045b2e7be4df248603f4079f770c1eb7cd9628c 100644 (file)
@@ -96,7 +96,7 @@ class SpawnProcess(SubProcess):
                        # spawn failed
                        self._unregister()
                        self._set_returncode((self.pid, retval))
-                       self.wait()
+                       self._async_wait()
                        return
 
                self.pid = retval[0]