diff options
author | Zac Medico <zmedico@gentoo.org> | 2008-07-10 03:40:39 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2008-07-10 03:40:39 +0000 |
commit | 15a5d41a961628db7e7e3f9a8b8214ea3111a880 (patch) | |
tree | bddf3da7628cc1af51b0c2b86d6c448d588a86c7 | |
parent | dcf36ddfe69c9a2dd65fc80731623d719fe49954 (diff) | |
download | portage-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__.py | 24 |
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 |