Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11297 - main/trunk/pym/_emerge
Date: Thu, 31 Jul 2008 10:37:47
Message-Id: E1KOVXV-0005st-7w@stork.gentoo.org
1 Author: zmedico
2 Date: 2008-07-31 10:37:43 +0000 (Thu, 31 Jul 2008)
3 New Revision: 11297
4
5 Modified:
6 main/trunk/pym/_emerge/__init__.py
7 Log:
8 Bug #233458 - Fix AsynchronousTask exit listener handling so that an exit
9 listener will never get called after it's been passed into
10 removeExitListener(), since the caller of removeExitListener() needs to
11 be able to be able to trust that the given exit listener will not be
12 called under any circumstances.
13
14
15 Modified: main/trunk/pym/_emerge/__init__.py
16 ===================================================================
17 --- main/trunk/pym/_emerge/__init__.py 2008-07-31 07:25:35 UTC (rev 11296)
18 +++ main/trunk/pym/_emerge/__init__.py 2008-07-31 10:37:43 UTC (rev 11297)
19 @@ -1599,7 +1599,7 @@
20 """
21
22 __slots__ = ("background", "cancelled", "returncode") + \
23 - ("_exit_listeners", "_start_listeners")
24 + ("_exit_listeners", "_exit_listener_stack", "_start_listeners")
25
26 def start(self):
27 """
28 @@ -1665,6 +1665,8 @@
29
30 def removeExitListener(self, f):
31 if self._exit_listeners is None:
32 + if self._exit_listener_stack is not None:
33 + self._exit_listener_stack.remove(f)
34 return
35 self._exit_listeners.remove(f)
36
37 @@ -1680,12 +1682,22 @@
38
39 # This prevents recursion, in case one of the
40 # exit handlers triggers this method again by
41 - # calling wait().
42 - exit_listeners = self._exit_listeners
43 + # calling wait(). Use a stack that gives
44 + # removeExitListener() an opportunity to consume
45 + # listeners from the stack, before they can get
46 + # called below. This is necessary because a call
47 + # to one exit listener may result in a call to
48 + # removeExitListener() for another listener on
49 + # the stack. That listener needs to be removed
50 + # from the stack since it would be inconsistent
51 + # to call it after it has been been passed into
52 + # removeExitListener().
53 + self._exit_listener_stack = self._exit_listeners
54 self._exit_listeners = None
55
56 - for f in exit_listeners:
57 - f(self)
58 + self._exit_listener_stack.reverse()
59 + while self._exit_listener_stack:
60 + self._exit_listener_stack.pop()(self)
61
62 class PipeReader(AsynchronousTask):