summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-07-10 03:40:39 +0000
committerZac Medico <zmedico@gentoo.org>2008-07-10 03:40:39 +0000
commit15a5d41a961628db7e7e3f9a8b8214ea3111a880 (patch)
treebddf3da7628cc1af51b0c2b86d6c448d588a86c7
parentdcf36ddfe69c9a2dd65fc80731623d719fe49954 (diff)
downloadportage-15a5d41a961628db7e7e3f9a8b8214ea3111a880.tar.gz
portage-15a5d41a961628db7e7e3f9a8b8214ea3111a880.tar.bz2
portage-15a5d41a961628db7e7e3f9a8b8214ea3111a880.zip
* Fix AsynchronousTask._wait_hook() to prevent potential recursive calls
triggered when calling exit listeners. * Make SequentialTaskQueue use exit listeners to trigger scheduling as soon as a task exits. This makes it possible for the queues to automatically schedule new tasks while scheduler remains in it's poll() loop. svn path=/main/trunk/; revision=11008
-rw-r--r--pym/_emerge/__init__.py24
1 files changed, 22 insertions, 2 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index a1a3d6fe7..163e606a7 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -1545,7 +1545,14 @@ class AsynchronousTask(SlotObject):
"""
if self.returncode is not None and \
self._exit_listeners is not None:
- for f in self._exit_listeners:
+
+ # This prevents recursion, in case one of the
+ # exit handlers triggers this method again by
+ # calling wait().
+ exit_listeners = self._exit_listeners
+ self._exit_listeners = None
+
+ for f in exit_listeners:
f(self)
self._exit_listeners = None
@@ -7604,7 +7611,7 @@ class PollSelectAdapter(PollConstants):
class SequentialTaskQueue(SlotObject):
- __slots__ = ("max_jobs", "running_tasks", "_task_queue")
+ __slots__ = ("max_jobs", "running_tasks", "_task_queue", "_scheduling")
def __init__(self, **kwargs):
SlotObject.__init__(self, **kwargs)
@@ -7624,6 +7631,13 @@ class SequentialTaskQueue(SlotObject):
if not self:
return False
+ if self._scheduling:
+ # Ignore any recursive schedule() calls triggered via
+ # self._task_exit().
+ return False
+
+ self._scheduling = True
+
task_queue = self._task_queue
running_tasks = self.running_tasks
max_jobs = self.max_jobs
@@ -7640,12 +7654,18 @@ class SequentialTaskQueue(SlotObject):
task = task_queue.popleft()
cancelled = getattr(task, "cancelled", None)
if not cancelled:
+ task.addExitListener(self._task_exit)
task.start()
running_tasks.add(task)
state_changed = True
+ self._scheduling = False
+
return state_changed
+ def _task_exit(self, task):
+ self.schedule()
+
def clear(self):
self._task_queue.clear()
running_tasks = self.running_tasks