aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'portage_with_autodep/pym/_emerge/AsynchronousTask.py')
-rw-r--r--portage_with_autodep/pym/_emerge/AsynchronousTask.py45
1 files changed, 39 insertions, 6 deletions
diff --git a/portage_with_autodep/pym/_emerge/AsynchronousTask.py b/portage_with_autodep/pym/_emerge/AsynchronousTask.py
index 36522ca..7a193ce 100644
--- a/portage_with_autodep/pym/_emerge/AsynchronousTask.py
+++ b/portage_with_autodep/pym/_emerge/AsynchronousTask.py
@@ -1,8 +1,11 @@
-# Copyright 1999-2011 Gentoo Foundation
+# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
+import signal
+
from portage import os
-from _emerge.SlotObject import SlotObject
+from portage.util.SlotObject import SlotObject
+
class AsynchronousTask(SlotObject):
"""
Subclasses override _wait() and _poll() so that calls
@@ -14,7 +17,10 @@ class AsynchronousTask(SlotObject):
"""
__slots__ = ("background", "cancelled", "returncode") + \
- ("_exit_listeners", "_exit_listener_stack", "_start_listeners")
+ ("_exit_listeners", "_exit_listener_stack", "_start_listeners",
+ "_waiting")
+
+ _cancelled_returncode = - signal.SIGINT
def start(self):
"""
@@ -42,7 +48,12 @@ class AsynchronousTask(SlotObject):
def wait(self):
if self.returncode is None:
- self._wait()
+ if not self._waiting:
+ self._waiting = True
+ try:
+ self._wait()
+ finally:
+ self._waiting = False
self._wait_hook()
return self.returncode
@@ -50,10 +61,17 @@ class AsynchronousTask(SlotObject):
return self.returncode
def cancel(self):
+ """
+ Cancel the task, but do not wait for exit status. If asynchronous exit
+ notification is desired, then use addExitListener to add a listener
+ before calling this method.
+ NOTE: Synchronous waiting for status is not supported, since it would
+ be vulnerable to hitting the recursion limit when a large number of
+ tasks need to be terminated simultaneously, like in bug #402335.
+ """
if not self.cancelled:
self.cancelled = True
self._cancel()
- self.wait()
def _cancel(self):
"""
@@ -62,6 +80,17 @@ class AsynchronousTask(SlotObject):
"""
pass
+ def _was_cancelled(self):
+ """
+ If cancelled, set returncode if necessary and return True.
+ Otherwise, return False.
+ """
+ if self.cancelled:
+ if self.returncode is None:
+ self.returncode = self._cancelled_returncode
+ return True
+ return False
+
def addStartListener(self, f):
"""
The function will be called with one argument, a reference to self.
@@ -123,7 +152,11 @@ class AsynchronousTask(SlotObject):
self._exit_listener_stack = self._exit_listeners
self._exit_listeners = None
- self._exit_listener_stack.reverse()
+ # Execute exit listeners in reverse order, so that
+ # the last added listener is executed first. This
+ # allows SequentialTaskQueue to decrement its running
+ # task count as soon as one of its tasks exits, so that
+ # the value is accurate when other listeners execute.
while self._exit_listener_stack:
self._exit_listener_stack.pop()(self)