summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-12-30 17:01:59 -0800
committerZac Medico <zmedico@gentoo.org>2012-12-30 17:04:27 -0800
commita3100be184ba1cac2f672f0a1cadcf01690c6d3f (patch)
tree53fa53cd147e24c7230daa71ddd7821fd6803108
parent7ebb2f54877edb28621c33e380f8777b1b1dc201 (diff)
downloadportage-a3100be184ba1cac2f672f0a1cadcf01690c6d3f.tar.gz
portage-a3100be184ba1cac2f672f0a1cadcf01690c6d3f.tar.bz2
portage-a3100be184ba1cac2f672f0a1cadcf01690c6d3f.zip
AsynchronousTask: add _async_wait method
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.
-rw-r--r--pym/_emerge/AbstractEbuildProcess.py2
-rw-r--r--pym/_emerge/AsynchronousLock.py2
-rw-r--r--pym/_emerge/AsynchronousTask.py14
-rw-r--r--pym/_emerge/BinpkgFetcher.py2
-rw-r--r--pym/_emerge/BinpkgVerifier.py5
-rw-r--r--pym/_emerge/EbuildBuild.py4
-rw-r--r--pym/_emerge/EbuildFetcher.py6
-rw-r--r--pym/_emerge/EbuildMetadataPhase.py6
-rw-r--r--pym/_emerge/MergeListItem.py2
-rw-r--r--pym/_emerge/PackageUninstall.py6
-rw-r--r--pym/_emerge/SpawnProcess.py2
11 files changed, 32 insertions, 19 deletions
diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py
index 597208f52..6d12cd999 100644
--- a/pym/_emerge/AbstractEbuildProcess.py
+++ b/pym/_emerge/AbstractEbuildProcess.py
@@ -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:
diff --git a/pym/_emerge/AsynchronousLock.py b/pym/_emerge/AsynchronousLock.py
index b4de779f9..5bb9663a1 100644
--- a/pym/_emerge/AsynchronousLock.py
+++ b/pym/_emerge/AsynchronousLock.py
@@ -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 \
diff --git a/pym/_emerge/AsynchronousTask.py b/pym/_emerge/AsynchronousTask.py
index 7a193ce7d..b540575d8 100644
--- a/pym/_emerge/AsynchronousTask.py
+++ b/pym/_emerge/AsynchronousTask.py
@@ -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
diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py
index 14f2552cb..099d3c498 100644
--- a/pym/_emerge/BinpkgFetcher.py
+++ b/pym/_emerge/BinpkgFetcher.py
@@ -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]
diff --git a/pym/_emerge/BinpkgVerifier.py b/pym/_emerge/BinpkgVerifier.py
index 0052967f6..fd4f266a1 100644
--- a/pym/_emerge/BinpkgVerifier.py
+++ b/pym/_emerge/BinpkgVerifier.py
@@ -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()
diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py
index cec63d992..599875a32 100644
--- a/pym/_emerge/EbuildBuild.py
+++ b/pym/_emerge/EbuildBuild.py
@@ -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
diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py
index 3cbe1b899..df790b0d3 100644
--- a/pym/_emerge/EbuildFetcher.py
+++ b/pym/_emerge/EbuildFetcher.py
@@ -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")
diff --git a/pym/_emerge/EbuildMetadataPhase.py b/pym/_emerge/EbuildMetadataPhase.py
index cc8d77593..89734e045 100644
--- a/pym/_emerge/EbuildMetadataPhase.py
+++ b/pym/_emerge/EbuildMetadataPhase.py
@@ -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]
diff --git a/pym/_emerge/MergeListItem.py b/pym/_emerge/MergeListItem.py
index 371e2e2e2..172dfccdf 100644
--- a/pym/_emerge/MergeListItem.py
+++ b/pym/_emerge/MergeListItem.py
@@ -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
diff --git a/pym/_emerge/PackageUninstall.py b/pym/_emerge/PackageUninstall.py
index eb6a947a5..16c2f749b 100644
--- a/pym/_emerge/PackageUninstall.py
+++ b/pym/_emerge/PackageUninstall.py
@@ -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,),
diff --git a/pym/_emerge/SpawnProcess.py b/pym/_emerge/SpawnProcess.py
index 45d709517..2045b2e7b 100644
--- a/pym/_emerge/SpawnProcess.py
+++ b/pym/_emerge/SpawnProcess.py
@@ -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]