Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: build/android/pylib/utils/reraiser_thread.py

Issue 636273004: Make TimeoutRetryThread's stoppable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Thread and ThreadGroup that reraise exceptions on the main thread.""" 5 """Thread and ThreadGroup that reraise exceptions on the main thread."""
6 # pylint: disable=W0212 6 # pylint: disable=W0212
7 7
8 import logging 8 import logging
9 import sys 9 import sys
10 import threading 10 import threading
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 if not args: 51 if not args:
52 args = [] 52 args = []
53 if not kwargs: 53 if not kwargs:
54 kwargs = {} 54 kwargs = {}
55 self.daemon = True 55 self.daemon = True
56 self._func = func 56 self._func = func
57 self._args = args 57 self._args = args
58 self._kwargs = kwargs 58 self._kwargs = kwargs
59 self._ret = None 59 self._ret = None
60 self._exc_info = None 60 self._exc_info = None
61 self._stopped = False
61 62
62 def ReraiseIfException(self): 63 def ReraiseIfException(self):
63 """Reraise exception if an exception was raised in the thread.""" 64 """Reraise exception if an exception was raised in the thread."""
64 if self._exc_info: 65 if self._exc_info:
65 raise self._exc_info[0], self._exc_info[1], self._exc_info[2] 66 raise self._exc_info[0], self._exc_info[1], self._exc_info[2]
66 67
67 def GetReturnValue(self): 68 def GetReturnValue(self):
68 """Reraise exception if present, otherwise get the return value.""" 69 """Reraise exception if present, otherwise get the return value."""
69 self.ReraiseIfException() 70 self.ReraiseIfException()
70 return self._ret 71 return self._ret
71 72
73 def StopThread(self):
jbudorick 2014/10/24 17:30:51 I don't think we want to provide this in reraiser_
perezju 2014/10/27 11:07:07 Looking around, e.g. http://stackoverflow.com/ques
jbudorick 2014/10/27 19:15:36 I'm not sure this is better than what we do now. I
perezju 2014/10/28 14:31:17 Just for fun, trying to reboot with a very low tim
74 """Request this thread to stop."""
75 self._stopped = True
76
77 def Stopped(self):
78 return self._stopped
79
72 #override 80 #override
73 def run(self): 81 def run(self):
74 """Overrides Thread.run() to add support for reraising exceptions.""" 82 """Overrides Thread.run() to add support for reraising exceptions."""
75 try: 83 try:
76 self._ret = self._func(*self._args, **self._kwargs) 84 self._ret = self._func(*self._args, **self._kwargs)
77 except: # pylint: disable=W0702 85 except: # pylint: disable=W0702
78 self._exc_info = sys.exc_info() 86 self._exc_info = sys.exc_info()
79 87
80 88
81 class ReraiserThreadGroup(object): 89 class ReraiserThreadGroup(object):
(...skipping 15 matching lines...) Expand all
97 Args: 105 Args:
98 thread: a ReraiserThread object. 106 thread: a ReraiserThread object.
99 """ 107 """
100 self._threads.append(thread) 108 self._threads.append(thread)
101 109
102 def StartAll(self): 110 def StartAll(self):
103 """Start all threads.""" 111 """Start all threads."""
104 for thread in self._threads: 112 for thread in self._threads:
105 thread.start() 113 thread.start()
106 114
107 def _JoinAll(self, watcher=watchdog_timer.WatchdogTimer(None)): 115 def _JoinAll(self, watcher):
108 """Join all threads without stack dumps. 116 """Join all threads without stack dumps.
109 117
110 Reraises exceptions raised by the child threads and supports breaking 118 Reraises exceptions raised by the child threads and supports breaking
111 immediately on exceptions raised on the main thread. 119 immediately on exceptions raised on the main thread.
112 120
113 Args: 121 Args:
114 watcher: Watchdog object providing timeout, by default waits forever. 122 watcher: Watchdog object providing timeout, by default waits forever.
115 """ 123 """
116 alive_threads = self._threads[:] 124 alive_threads = self._threads[:]
117 while alive_threads: 125 while alive_threads:
118 for thread in alive_threads[:]: 126 for thread in alive_threads[:]:
119 if watcher.IsTimedOut(): 127 if watcher.IsTimedOut():
120 raise TimeoutError('Timed out waiting for %d of %d threads.' % 128 raise TimeoutError('Timed out waiting for %d of %d threads.' %
121 (len(alive_threads), len(self._threads))) 129 (len(alive_threads), len(self._threads)))
122 # Allow the main thread to periodically check for interrupts. 130 # Allow the main thread to periodically check for interrupts.
123 thread.join(0.1) 131 thread.join(0.1)
124 if not thread.isAlive(): 132 if not thread.isAlive():
125 alive_threads.remove(thread) 133 alive_threads.remove(thread)
126 # All threads are allowed to complete before reraising exceptions. 134 # All threads are allowed to complete before reraising exceptions.
127 for thread in self._threads: 135 for thread in self._threads:
128 thread.ReraiseIfException() 136 thread.ReraiseIfException()
129 137
130 def JoinAll(self, watcher=watchdog_timer.WatchdogTimer(None)): 138 def JoinAll(self, watcher=None):
131 """Join all threads. 139 """Join all threads.
132 140
133 Reraises exceptions raised by the child threads and supports breaking 141 Reraises exceptions raised by the child threads and supports breaking
134 immediately on exceptions raised on the main thread. Unfinished threads' 142 immediately on exceptions raised on the main thread. Unfinished threads'
135 stacks will be logged on watchdog timeout. 143 stacks will be logged on watchdog timeout.
136 144
137 Args: 145 Args:
138 watcher: Watchdog object providing timeout, by default waits forever. 146 watcher: Watchdog object providing timeout, by default waits forever.
139 """ 147 """
148 if watcher is None:
149 watcher=watchdog_timer.WatchdogTimer(None)
jbudorick 2014/10/24 17:30:52 nice catch. nit: spaces around =
140 try: 150 try:
141 self._JoinAll(watcher) 151 self._JoinAll(watcher)
142 except TimeoutError: 152 except TimeoutError:
143 for thread in (t for t in self._threads if t.isAlive()): 153 for thread in (t for t in self._threads if t.isAlive()):
144 LogThreadStack(thread) 154 LogThreadStack(thread)
155 thread.StopThread()
145 raise 156 raise
146 157
147 def GetAllReturnValues(self, watcher=watchdog_timer.WatchdogTimer(None)): 158 def GetAllReturnValues(self, watcher=watchdog_timer.WatchdogTimer(None)):
148 """Get all return values, joining all threads if necessary. 159 """Get all return values, joining all threads if necessary.
149 160
150 Args: 161 Args:
151 watcher: same as in |JoinAll|. Only used if threads are alive. 162 watcher: same as in |JoinAll|. Only used if threads are alive.
152 """ 163 """
153 if any([t.isAlive() for t in self._threads]): 164 if any([t.isAlive() for t in self._threads]):
154 self.JoinAll(watcher) 165 self.JoinAll(watcher)
155 return [t.GetReturnValue() for t in self._threads] 166 return [t.GetReturnValue() for t in self._threads]
156 167
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698