OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // This file defines a WatchDog thread that monitors the responsiveness of other | 5 // This file defines a WatchDog thread that monitors the responsiveness of other |
6 // browser threads like UI, IO, DB, FILE and CACHED threads. It also defines | 6 // browser threads like UI, IO, DB, FILE and CACHED threads. It also defines |
7 // ThreadWatcher class which performs health check on threads that would like to | 7 // ThreadWatcher class which performs health check on threads that would like to |
8 // be watched. This file also defines ThreadWatcherList class that has list of | 8 // be watched. This file also defines ThreadWatcherList class that has list of |
9 // all active ThreadWatcher objects. | 9 // all active ThreadWatcher objects. |
10 // | 10 // |
11 // ThreadWatcher class sends ping message to the watched thread and the watched | 11 // ThreadWatcher class sends ping message to the watched thread and the watched |
12 // thread responds back with a pong message. It uploads response time | 12 // thread responds back with a pong message. It uploads response time |
13 // (difference between ping and pong times) as a histogram. | 13 // (difference between ping and pong times) as a histogram. |
14 // | 14 // |
15 // TODO(raman): ThreadWatcher can detect hung threads. If a hung thread is | 15 // TODO(raman): ThreadWatcher can detect hung threads. If a hung thread is |
16 // detected, we should probably just crash, and allow the crash system to gather | 16 // detected, we should probably just crash, and allow the crash system to gather |
17 // then stack trace. | 17 // then stack trace. |
18 // | 18 // |
19 // Example Usage: | 19 // Example Usage: |
20 // | 20 // |
21 // The following is an example for watching responsiveness of IO thread. | 21 // The following is an example for watching responsiveness of watched (IO) |
22 // sleep_time specifies how often ping messages have to be sent to IO thread. | 22 // thread. |sleep_time| specifies how often ping messages have to be sent to |
23 // unresponsive_time is the wait time after ping message is sent, to check if | 23 // watched (IO) thread. |unresponsive_time| is the wait time after ping |
24 // we have received pong message or not. | 24 // message is sent, to check if we have received pong message or not. |
| 25 // |unresponsive_threshold| specifies the number of unanswered ping messages |
| 26 // after which watched (IO) thread is considered as not responsive. |
| 27 // |crash_on_hang| specifies if we want to crash the browser when the watched |
| 28 // (IO) thread has become sufficiently unresponsive, while other threads are |
| 29 // sufficiently responsive. |live_threads_threshold| specifies the number of |
| 30 // browser threads that are to be responsive when we want to crash the browser |
| 31 // because of hung watched (IO) thread. |
25 // | 32 // |
26 // base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(5); | 33 // base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(5); |
27 // base::TimeDelta unresponsive_time = base::TimeDelta::FromSeconds(10); | 34 // base::TimeDelta unresponsive_time = base::TimeDelta::FromSeconds(10); |
28 // ThreadWatcher::StartWatching(BrowserThread::IO, "IO", sleep_time, | 35 // uint32 unresponsive_threshold = ThreadWatcherList::kUnresponsiveCount; |
29 // unresponsive_time); | 36 // bool crash_on_hang = false; |
| 37 // uint32 live_threads_threshold = ThreadWatcherList::kLiveThreadsThreshold; |
| 38 // ThreadWatcher::StartWatching( |
| 39 // BrowserThread::IO, "IO", sleep_time, unresponsive_time, |
| 40 // unresponsive_threshold, crash_on_hang, live_threads_threshold); |
30 | 41 |
31 #ifndef CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ | 42 #ifndef CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ |
32 #define CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ | 43 #define CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ |
33 | 44 |
34 #include <map> | 45 #include <map> |
| 46 #include <set> |
35 #include <string> | 47 #include <string> |
36 #include <vector> | 48 #include <vector> |
37 | 49 |
38 #include "base/basictypes.h" | 50 #include "base/basictypes.h" |
| 51 #include "base/command_line.h" |
39 #include "base/gtest_prod_util.h" | 52 #include "base/gtest_prod_util.h" |
40 #include "base/memory/ref_counted.h" | 53 #include "base/memory/ref_counted.h" |
41 #include "base/memory/scoped_ptr.h" | 54 #include "base/memory/scoped_ptr.h" |
42 #include "base/message_loop.h" | 55 #include "base/message_loop.h" |
43 #include "base/metrics/histogram.h" | 56 #include "base/metrics/histogram.h" |
44 #include "base/synchronization/lock.h" | 57 #include "base/synchronization/lock.h" |
45 #include "base/task.h" | 58 #include "base/task.h" |
46 #include "base/threading/thread.h" | 59 #include "base/threading/thread.h" |
47 #include "base/time.h" | 60 #include "base/time.h" |
48 #include "content/browser/browser_thread.h" | 61 #include "content/browser/browser_thread.h" |
49 #include "content/common/notification_observer.h" | 62 #include "content/common/notification_observer.h" |
50 #include "content/common/notification_registrar.h" | 63 #include "content/common/notification_registrar.h" |
51 | 64 |
52 class CustomThreadWatcher; | 65 class CustomThreadWatcher; |
53 class ThreadWatcherList; | 66 class ThreadWatcherList; |
| 67 class ThreadWatcherObserver; |
54 | 68 |
55 // This class performs health check on threads that would like to be watched. | 69 // This class performs health check on threads that would like to be watched. |
56 class ThreadWatcher { | 70 class ThreadWatcher { |
57 public: | 71 public: |
58 // This method starts performing health check on the given thread_id. It will | 72 // This method starts performing health check on the given |thread_id|. It |
59 // create ThreadWatcher object for the given thread_id, thread_name, | 73 // will create ThreadWatcher object for the given |thread_id|, |thread_name|. |
60 // sleep_time and unresponsive_time. sleep_time_ is the wait time between ping | 74 // |sleep_time| is the wait time between ping messages. |unresponsive_time| is |
61 // messages. unresponsive_time_ is the wait time after ping message is sent, | 75 // the wait time after ping message is sent, to check if we have received pong |
62 // to check if we have received pong message or not. It will register that | 76 // message or not. |unresponsive_threshold| is used to determine if the thread |
63 // ThreadWatcher object and activate the thread watching of the given | 77 // is responsive or not. The watched thread is considered unresponsive if it |
64 // thread_id. | 78 // hasn't responded with a pong message for |unresponsive_threshold| number of |
| 79 // ping messages. |crash_on_hang| specifies if browser should be crashed when |
| 80 // the watched thread is unresponsive. |live_threads_threshold| specifies the |
| 81 // number of browser threads that are to be responsive when we want to crash |
| 82 // the browser and watched thread has become sufficiently unresponsive. It |
| 83 // will register that ThreadWatcher object and activate the thread watching of |
| 84 // the given thread_id. |
65 static void StartWatching(const BrowserThread::ID& thread_id, | 85 static void StartWatching(const BrowserThread::ID& thread_id, |
66 const std::string& thread_name, | 86 const std::string& thread_name, |
67 const base::TimeDelta& sleep_time, | 87 const base::TimeDelta& sleep_time, |
68 const base::TimeDelta& unresponsive_time); | 88 const base::TimeDelta& unresponsive_time, |
| 89 uint32 unresponsive_threshold, |
| 90 bool crash_on_hang, |
| 91 uint32 live_threads_threshold); |
69 | 92 |
70 // Return the thread_id of the thread being watched. | 93 // Return the |thread_id_| of the thread being watched. |
71 BrowserThread::ID thread_id() const { return thread_id_; } | 94 BrowserThread::ID thread_id() const { return thread_id_; } |
72 | 95 |
73 // Return the name of the thread being watched. | 96 // Return the name of the thread being watched. |
74 std::string thread_name() const { return thread_name_; } | 97 std::string thread_name() const { return thread_name_; } |
75 | 98 |
76 // Return the sleep time between ping messages to be sent to the thread. | 99 // Return the sleep time between ping messages to be sent to the thread. |
77 base::TimeDelta sleep_time() const { return sleep_time_; } | 100 base::TimeDelta sleep_time() const { return sleep_time_; } |
78 | 101 |
79 // Return the the wait time to check the responsiveness of the thread. | 102 // Return the the wait time to check the responsiveness of the thread. |
80 base::TimeDelta unresponsive_time() const { return unresponsive_time_; } | 103 base::TimeDelta unresponsive_time() const { return unresponsive_time_; } |
81 | 104 |
82 // Returns true if we are montioring the thread. | 105 // Returns true if we are montioring the thread. |
83 bool active() const { return active_; } | 106 bool active() const { return active_; } |
84 | 107 |
85 // Returns ping_time_ (used by unit tests). | 108 // Returns |ping_time_| (used by unit tests). |
86 base::TimeTicks ping_time() const { return ping_time_; } | 109 base::TimeTicks ping_time() const { return ping_time_; } |
87 | 110 |
88 // Returns ping_sequence_number_ (used by unit tests). | 111 // Returns |ping_sequence_number_| (used by unit tests). |
89 uint64 ping_sequence_number() const { return ping_sequence_number_; } | 112 uint64 ping_sequence_number() const { return ping_sequence_number_; } |
90 | 113 |
91 protected: | 114 protected: |
92 // Construct a ThreadWatcher for the given thread_id. sleep_time_ is the | 115 // Construct a ThreadWatcher for the given |thread_id|. |sleep_time| is the |
93 // wait time between ping messages. unresponsive_time_ is the wait time after | 116 // wait time between ping messages. |unresponsive_time| is the wait time after |
94 // ping message is sent, to check if we have received pong message or not. | 117 // ping message is sent, to check if we have received pong message or not. |
95 ThreadWatcher(const BrowserThread::ID& thread_id, | 118 ThreadWatcher(const BrowserThread::ID& thread_id, |
96 const std::string& thread_name, | 119 const std::string& thread_name, |
97 const base::TimeDelta& sleep_time, | 120 const base::TimeDelta& sleep_time, |
98 const base::TimeDelta& unresponsive_time); | 121 const base::TimeDelta& unresponsive_time, |
| 122 uint32 unresponsive_threshold, |
| 123 bool crash_on_hang, |
| 124 uint32 live_threads_threshold); |
99 virtual ~ThreadWatcher(); | 125 virtual ~ThreadWatcher(); |
100 | 126 |
101 // This method activates the thread watching which starts ping/pong messaging. | 127 // This method activates the thread watching which starts ping/pong messaging. |
102 virtual void ActivateThreadWatching(); | 128 virtual void ActivateThreadWatching(); |
103 | 129 |
104 // This method de-activates the thread watching and revokes all tasks. | 130 // This method de-activates the thread watching and revokes all tasks. |
105 virtual void DeActivateThreadWatching(); | 131 virtual void DeActivateThreadWatching(); |
106 | 132 |
107 // This will ensure that the watching is actively taking place, and awaken | 133 // This will ensure that the watching is actively taking place, and awaken |
108 // (i.e., post a PostPingMessage) if the watcher has stopped pinging due to | 134 // (i.e., post a PostPingMessage()) if the watcher has stopped pinging due to |
109 // lack of user activity. It will also reset ping_count_ to kPingCount. | 135 // lack of user activity. It will also reset |ping_count_| to |kPingCount|. |
110 virtual void WakeUp(); | 136 virtual void WakeUp(); |
111 | 137 |
112 // This method records when ping message was sent and it will Post a task | 138 // This method records when ping message was sent and it will Post a task |
113 // (OnPingMessage) to the watched thread that does nothing but respond with | 139 // (OnPingMessage()) to the watched thread that does nothing but respond with |
114 // OnPongMessage. It also posts a task (OnCheckResponsiveness) to check | 140 // OnPongMessage(). It also posts a task (OnCheckResponsiveness()) to check |
115 // responsiveness of monitored thread that would be called after waiting | 141 // responsiveness of monitored thread that would be called after waiting |
116 // unresponsive_time_. | 142 // |unresponsive_time_|. |
117 // This method is accessible on WatchDogThread. | 143 // This method is accessible on WatchDogThread. |
118 virtual void PostPingMessage(); | 144 virtual void PostPingMessage(); |
119 | 145 |
120 // This method handles a Pong Message from watched thread. It will track the | 146 // This method handles a Pong Message from watched thread. It will track the |
121 // response time (pong time minus ping time) via histograms. It posts a | 147 // response time (pong time minus ping time) via histograms. It posts a |
122 // PostPingMessage task that would be called after waiting sleep_time_. It | 148 // PostPingMessage() task that would be called after waiting |sleep_time_|. It |
123 // increments ping_sequence_number_ by 1. | 149 // increments |ping_sequence_number_| by 1. |
124 // This method is accessible on WatchDogThread. | 150 // This method is accessible on WatchDogThread. |
125 virtual void OnPongMessage(uint64 ping_sequence_number); | 151 virtual void OnPongMessage(uint64 ping_sequence_number); |
126 | 152 |
127 // This method will determine if the watched thread is responsive or not. If | 153 // This method will determine if the watched thread is responsive or not. If |
128 // the latest ping_sequence_number_ is not same as the ping_sequence_number | 154 // the latest |ping_sequence_number_| is not same as the |
129 // that is passed in, then we can assume that watched thread has responded | 155 // |ping_sequence_number| that is passed in, then we can assume that watched |
130 // with a pong message. | 156 // thread has responded with a pong message. |
131 // This method is accessible on WatchDogThread. | 157 // This method is accessible on WatchDogThread. |
132 virtual bool OnCheckResponsiveness(uint64 ping_sequence_number); | 158 virtual bool OnCheckResponsiveness(uint64 ping_sequence_number); |
133 | 159 |
134 private: | 160 private: |
135 friend class ThreadWatcherList; | 161 friend class ThreadWatcherList; |
136 friend class CustomThreadWatcher; | 162 friend class CustomThreadWatcher; |
137 | 163 |
138 // Allow tests to access our innards for testing purposes. | 164 // Allow tests to access our innards for testing purposes. |
139 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, Registration); | 165 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, Registration); |
140 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadResponding); | 166 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadResponding); |
141 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadNotResponding); | 167 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadNotResponding); |
142 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsResponding); | 168 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsResponding); |
143 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsNotResponding); | 169 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsNotResponding); |
144 | 170 |
145 // Post constructor initialization. | 171 // Post constructor initialization. |
146 void Initialize(); | 172 void Initialize(); |
147 | 173 |
148 // Watched thread does nothing except post callback_task to the WATCHDOG | 174 // Watched thread does nothing except post callback_task to the WATCHDOG |
149 // Thread. This method is called on watched thread. | 175 // Thread. This method is called on watched thread. |
150 static void OnPingMessage(const BrowserThread::ID& thread_id, | 176 static void OnPingMessage(const BrowserThread::ID& thread_id, |
151 Task* callback_task); | 177 Task* callback_task); |
152 | 178 |
153 // This method resets unresponsive_count_ to zero because watched thread is | 179 // This method resets |unresponsive_count_| to zero because watched thread is |
154 // responding to the ping message with a pong message. | 180 // responding to the ping message with a pong message. |
155 void ResetHangCounters(); | 181 void ResetHangCounters(); |
156 | 182 |
157 // This method records watched thread is not responding to the ping message. | 183 // This method records watched thread is not responding to the ping message. |
158 // It increments unresponsive_count_ by 1. | 184 // It increments |unresponsive_count_| by 1. |
159 void GotNoResponse(); | 185 void GotNoResponse(); |
160 | 186 |
| 187 // This method returns true if the watched thread has not responded with a |
| 188 // pong message for |unresponsive_threshold_| number of ping messages. |
| 189 bool IsVeryUnresponsive(); |
| 190 |
161 // This is the number of ping messages to be sent when the user is idle. | 191 // This is the number of ping messages to be sent when the user is idle. |
162 // ping_count_ will be initialized to kPingCount whenever user becomes active. | 192 // ping_count_ will be initialized to kPingCount whenever user becomes active. |
163 static const int kPingCount; | 193 static const int kPingCount; |
164 | 194 |
165 // This value is used to determine if the watched thread is responsive or not. | 195 // The |thread_id_| of the thread being watched. Only one instance can exist |
166 // If unresponsive_count_ is less than kUnresponsiveCount then watched thread | 196 // for the given |thread_id_| of the thread being watched. |
167 // is considered as responsive (in responsive_count_histogram_) otherwise it | |
168 // is considered as unresponsive (in unresponsive_count_histogram_). | |
169 static const int kUnresponsiveCount; | |
170 | |
171 // The thread_id of the thread being watched. Only one instance can exist for | |
172 // the given thread_id of the thread being watched. | |
173 const BrowserThread::ID thread_id_; | 197 const BrowserThread::ID thread_id_; |
174 | 198 |
175 // The name of the thread being watched. | 199 // The name of the thread being watched. |
176 const std::string thread_name_; | 200 const std::string thread_name_; |
177 | 201 |
178 // It is the sleep time between between the receipt of a pong message back, | 202 // It is the sleep time between the receipt of a pong message back, and the |
179 // and the sending of another ping message. | 203 // sending of another ping message. |
180 const base::TimeDelta sleep_time_; | 204 const base::TimeDelta sleep_time_; |
181 | 205 |
182 // It is the duration from sending a ping message, until we check status to be | 206 // It is the duration from sending a ping message, until we check status to be |
183 // sure a pong message has been returned. | 207 // sure a pong message has been returned. |
184 const base::TimeDelta unresponsive_time_; | 208 const base::TimeDelta unresponsive_time_; |
185 | 209 |
186 // This is the last time when ping message was sent. | 210 // This is the last time when ping message was sent. |
187 base::TimeTicks ping_time_; | 211 base::TimeTicks ping_time_; |
188 | 212 |
189 // This is the last time when we got pong message. | 213 // This is the last time when we got pong message. |
(...skipping 10 matching lines...) Expand all Loading... |
200 // The counter tracks least number of ping messages that will be sent to | 224 // The counter tracks least number of ping messages that will be sent to |
201 // watched thread before the ping-pong mechanism will go into an extended | 225 // watched thread before the ping-pong mechanism will go into an extended |
202 // sleep. If this value is zero, then the mechanism is in an extended sleep, | 226 // sleep. If this value is zero, then the mechanism is in an extended sleep, |
203 // and awaiting some observed user action before continuing. | 227 // and awaiting some observed user action before continuing. |
204 int ping_count_; | 228 int ping_count_; |
205 | 229 |
206 // Histogram that keeps track of response times for the watched thread. | 230 // Histogram that keeps track of response times for the watched thread. |
207 base::Histogram* response_time_histogram_; | 231 base::Histogram* response_time_histogram_; |
208 | 232 |
209 // Histogram that keeps track of unresponsive time since the last pong message | 233 // Histogram that keeps track of unresponsive time since the last pong message |
210 // when we got no response (GotNoResponse) from the watched thread. | 234 // when we got no response (GotNoResponse()) from the watched thread. |
211 base::Histogram* unresponsive_time_histogram_; | 235 base::Histogram* unresponsive_time_histogram_; |
212 | 236 |
213 // Histogram that keeps track of how many threads are responding when we got | 237 // Histogram that keeps track of how many threads are responding when we got |
214 // no response (GotNoResponse) from the watched thread. | 238 // no response (GotNoResponse()) from the watched thread. |
215 base::Histogram* responsive_count_histogram_; | 239 base::Histogram* responsive_count_histogram_; |
216 | 240 |
217 // Histogram that keeps track of how many threads are not responding when we | 241 // Histogram that keeps track of how many threads are not responding when we |
218 // got no response (GotNoResponse) from the watched thread. Count includes the | 242 // got no response (GotNoResponse()) from the watched thread. Count includes |
219 // thread that got no response. | 243 // the thread that got no response. |
220 base::Histogram* unresponsive_count_histogram_; | 244 base::Histogram* unresponsive_count_histogram_; |
221 | 245 |
222 // This counter tracks the unresponsiveness of watched thread. If this value | 246 // This counter tracks the unresponsiveness of watched thread. If this value |
223 // is zero then watched thread has responded with a pong message. This is | 247 // is zero then watched thread has responded with a pong message. This is |
224 // incremented by 1 when we got no response (GotNoResponse) from the watched | 248 // incremented by 1 when we got no response (GotNoResponse()) from the watched |
225 // thread. | 249 // thread. |
226 int unresponsive_count_; | 250 uint32 unresponsive_count_; |
227 | 251 |
228 // This is set to true when we would have crashed the browser because the | 252 // This is set to true when we would have crashed the browser because the |
229 // watched thread hasn't responded atleast 6 times. It is reset to false when | 253 // watched thread hasn't responded atleast 6 times. It is reset to false when |
230 // watched thread responds with a pong message. | 254 // watched thread responds with a pong message. |
231 bool hung_processing_complete_; | 255 bool hung_processing_complete_; |
232 | 256 |
| 257 // This is used to determine if the watched thread is responsive or not. If |
| 258 // watched thread's |unresponsive_count_| is greater than or equal to |
| 259 // |unresponsive_threshold_| then we would consider it as unresponsive. |
| 260 uint32 unresponsive_threshold_; |
| 261 |
| 262 // This is set to true if we want to crash the browser when the watched thread |
| 263 // has become sufficiently unresponsive, while other threads are sufficiently |
| 264 // responsive. |
| 265 bool crash_on_hang_; |
| 266 |
| 267 // This specifies the number of browser threads that are to be responsive when |
| 268 // we want to crash the browser because watched thread has become sufficiently |
| 269 // unresponsive. |
| 270 uint32 live_threads_threshold_; |
| 271 |
233 // We use this factory to create callback tasks for ThreadWatcher object. We | 272 // We use this factory to create callback tasks for ThreadWatcher object. We |
234 // use this during ping-pong messaging between WatchDog thread and watched | 273 // use this during ping-pong messaging between WatchDog thread and watched |
235 // thread. | 274 // thread. |
236 ScopedRunnableMethodFactory<ThreadWatcher> method_factory_; | 275 ScopedRunnableMethodFactory<ThreadWatcher> method_factory_; |
237 | 276 |
238 DISALLOW_COPY_AND_ASSIGN(ThreadWatcher); | 277 DISALLOW_COPY_AND_ASSIGN(ThreadWatcher); |
239 }; | 278 }; |
240 | 279 |
241 // Class with a list of all active thread watchers. A thread watcher is active | 280 // Class with a list of all active thread watchers. A thread watcher is active |
242 // if it has been registered, which includes determing the histogram name. This | 281 // if it has been registered, which includes determing the histogram name. This |
243 // class provides utility functions to start and stop watching all browser | 282 // class provides utility functions to start and stop watching all browser |
244 // threads. Only one instance of this class exists. | 283 // threads. Only one instance of this class exists. |
245 class ThreadWatcherList : public NotificationObserver { | 284 class ThreadWatcherList { |
246 public: | 285 public: |
247 // A map from BrowserThread to the actual instances. | 286 // A map from BrowserThread to the actual instances. |
248 typedef std::map<BrowserThread::ID, ThreadWatcher*> RegistrationList; | 287 typedef std::map<BrowserThread::ID, ThreadWatcher*> RegistrationList; |
249 | 288 |
250 // This singleton holds the global list of registered ThreadWatchers. | |
251 ThreadWatcherList(); | |
252 // Destructor deletes all registered ThreadWatcher instances. | |
253 virtual ~ThreadWatcherList(); | |
254 | |
255 // Register() stores a pointer to the given ThreadWatcher in a global map. | |
256 static void Register(ThreadWatcher* watcher); | |
257 | |
258 // This method returns true if the ThreadWatcher object is registerd. | |
259 static bool IsRegistered(const BrowserThread::ID thread_id); | |
260 | |
261 // This method posts a task on WatchDogThread to start watching all browser | 289 // This method posts a task on WatchDogThread to start watching all browser |
262 // threads. | 290 // threads. |
263 // This method is accessible on UI thread. | 291 // This method is accessible on UI thread. |
264 static void StartWatchingAll(); | 292 static void StartWatchingAll(const CommandLine& command_line); |
265 | 293 |
266 // This method posts a task on WatchDogThread to RevokeAll tasks and to | 294 // This method posts a task on WatchDogThread to RevokeAll tasks and to |
267 // deactive thread watching of other threads and tell NotificationService to | 295 // deactive thread watching of other threads and tell NotificationService to |
268 // stop calling Observe. | 296 // stop calling Observe. |
269 // This method is accessible on UI thread. | 297 // This method is accessible on UI thread. |
270 static void StopWatchingAll(); | 298 static void StopWatchingAll(); |
271 | 299 |
272 // RemoveAll NotificationTypes that are being observed. | 300 // Register() stores a pointer to the given ThreadWatcher in a global map. |
273 // This method is accessible on UI thread. | 301 static void Register(ThreadWatcher* watcher); |
274 static void RemoveNotifications(); | |
275 | 302 |
276 // This method returns number of watched threads that have responded and | 303 // This method returns true if the ThreadWatcher object is registerd. |
277 // threads that have not responded with a pong message. | 304 static bool IsRegistered(const BrowserThread::ID thread_id); |
278 static void GetStatusOfThreads(int* no_of_responding_threads, | 305 |
279 int* no_of_unresponding_threads); | 306 // This method returns number of responsive and unresponsive watched threads. |
| 307 static void GetStatusOfThreads(uint32* responding_thread_count, |
| 308 uint32* unresponding_thread_count); |
| 309 |
| 310 // This will ensure that the watching is actively taking place, and awaken |
| 311 // all thread watchers that are registered. |
| 312 static void WakeUpAll(); |
280 | 313 |
281 private: | 314 private: |
282 // Allow tests to access our innards for testing purposes. | 315 // Allow tests to access our innards for testing purposes. |
283 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, Registration); | 316 friend class CustomThreadWatcher; |
| 317 friend class ThreadWatcherTest; |
| 318 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, CommandLineArgs); |
284 | 319 |
285 // Delete all thread watcher objects and remove them from global map. | 320 // This singleton holds the global list of registered ThreadWatchers. |
286 // This method is accessible on WatchDogThread. | 321 ThreadWatcherList(); |
287 void DeleteAll(); | |
288 | 322 |
289 // This will ensure that the watching is actively taking place. It will wakeup | 323 // Destructor deletes all registered ThreadWatcher instances. |
290 // all thread watchers every 2 seconds. This is the implementation of | 324 virtual ~ThreadWatcherList(); |
291 // NotificationObserver. When a matching notification is posted to the | |
292 // notification service, this method is called. | |
293 // This method is accessible on UI thread. | |
294 virtual void Observe(NotificationType type, | |
295 const NotificationSource& source, | |
296 const NotificationDetails& details); | |
297 | 325 |
298 // This will ensure that the watching is actively taking place, and awaken | 326 // Parses the command line to get |unresponsive_threshold| from |
299 // all thread watchers that are registered. | 327 // switches::kCrashOnHangSeconds, |crash_on_hang_thread_names| from |
300 // This method is accessible on WatchDogThread. | 328 // switches::kCrashOnHangThreads and |live_threads_threshold| from |
301 virtual void WakeUpAll(); | 329 // switches::kCrashOnLive. |crash_on_hang_thread_names| is the set of watched |
| 330 // thread's names that are to be crashed if they are not responding. |
| 331 static void ParseCommandLine( |
| 332 const CommandLine& command_line, |
| 333 uint32* unresponsive_threshold, |
| 334 std::set<std::string>* crash_on_hang_thread_names, |
| 335 uint32* live_threads_threshold); |
| 336 |
| 337 // This constructs the |ThreadWatcherList| singleton and starts watching |
| 338 // browser threads by calling StartWatching() on each browser thread that is |
| 339 // watched. |
| 340 static void InitializeAndStartWatching( |
| 341 uint32 unresponsive_threshold, |
| 342 const std::set<std::string>& crash_on_hang_thread_names, |
| 343 uint32 live_threads_threshold); |
| 344 |
| 345 // This method calls ThreadWatcher::StartWatching() to perform health check on |
| 346 // the given |thread_id|. |
| 347 static void StartWatching( |
| 348 const BrowserThread::ID& thread_id, |
| 349 const std::string& thread_name, |
| 350 const base::TimeDelta& sleep_time, |
| 351 const base::TimeDelta& unresponsive_time, |
| 352 uint32 unresponsive_threshold, |
| 353 const std::set<std::string>& crash_on_hang_thread_names, |
| 354 uint32 live_threads_threshold); |
| 355 |
| 356 // Delete all thread watcher objects and remove them from global map. It also |
| 357 // deletes |g_thread_watcher_list_|. |
| 358 static void DeleteAll(); |
302 | 359 |
303 // The Find() method can be used to test to see if a given ThreadWatcher was | 360 // The Find() method can be used to test to see if a given ThreadWatcher was |
304 // already registered, or to retrieve a pointer to it from the global map. | 361 // already registered, or to retrieve a pointer to it from the global map. |
305 static ThreadWatcher* Find(const BrowserThread::ID& thread_id); | 362 static ThreadWatcher* Find(const BrowserThread::ID& thread_id); |
306 | 363 |
307 // Helper function should be called only while holding lock_. | 364 // The singleton of this class and is used to keep track of information about |
308 ThreadWatcher* PreLockedFind(const BrowserThread::ID& thread_id); | 365 // threads that are being watched. |
309 | 366 static ThreadWatcherList* g_thread_watcher_list_; |
310 static ThreadWatcherList* global_; // The singleton of this class. | |
311 | 367 |
312 // This is the wait time between ping messages. | 368 // This is the wait time between ping messages. |
313 static const int kSleepSeconds; | 369 static const int kSleepSeconds; |
314 | 370 |
315 // This is the wait time after ping message is sent, to check if we have | 371 // This is the wait time after ping message is sent, to check if we have |
316 // received pong message or not. | 372 // received pong message or not. |
317 static const int kUnresponsiveSeconds; | 373 static const int kUnresponsiveSeconds; |
318 | 374 |
319 // Lock for access to registered_. | 375 // Default values for |unresponsive_threshold|. |
320 base::Lock lock_; | 376 static const int kUnresponsiveCount; |
| 377 |
| 378 // Default values for |live_threads_threshold|. |
| 379 static const int kLiveThreadsThreshold; |
321 | 380 |
322 // Map of all registered watched threads, from thread_id to ThreadWatcher. | 381 // Map of all registered watched threads, from thread_id to ThreadWatcher. |
323 RegistrationList registered_; | 382 RegistrationList registered_; |
324 | 383 |
| 384 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList); |
| 385 }; |
| 386 |
| 387 // This class ensures that the thread watching is actively taking place. Only |
| 388 // one instance of this class exists. |
| 389 class ThreadWatcherObserver : public NotificationObserver { |
| 390 public: |
| 391 // Registers |g_thread_watcher_observer_| as the Notifications observer. |
| 392 // |wakeup_interval| specifies how often to wake up thread watchers. This |
| 393 // method is accessible on UI thread. |
| 394 static void SetupNotifications(const base::TimeDelta& wakeup_interval); |
| 395 |
| 396 // Removes all NotificationTypes from |registrar_| and deletes |
| 397 // |g_thread_watcher_observer_|. This method is accessible on UI thread. |
| 398 static void RemoveNotifications(); |
| 399 |
| 400 private: |
| 401 // Constructor of |g_thread_watcher_observer_| singleton. |
| 402 explicit ThreadWatcherObserver(const base::TimeDelta& wakeup_interval); |
| 403 |
| 404 // Destructor of |g_thread_watcher_observer_| singleton. |
| 405 virtual ~ThreadWatcherObserver(); |
| 406 |
| 407 // This ensures all thread watchers are active because there is some user |
| 408 // activity. It will wake up all thread watchers every |wakeup_interval_| |
| 409 // seconds. This is the implementation of NotificationObserver. When a |
| 410 // matching notification is posted to the notification service, this method is |
| 411 // called. |
| 412 virtual void Observe(NotificationType type, |
| 413 const NotificationSource& source, |
| 414 const NotificationDetails& details); |
| 415 |
| 416 // The singleton of this class. |
| 417 static ThreadWatcherObserver* g_thread_watcher_observer_; |
| 418 |
325 // The registrar that holds NotificationTypes to be observed. | 419 // The registrar that holds NotificationTypes to be observed. |
326 NotificationRegistrar registrar_; | 420 NotificationRegistrar registrar_; |
327 | 421 |
328 // This is the last time when woke all thread watchers up. | 422 // This is the last time when woke all thread watchers up. |
329 base::TimeTicks last_wakeup_time_; | 423 base::TimeTicks last_wakeup_time_; |
330 | 424 |
331 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList); | 425 // It is the time interval between wake up calls to thread watchers. |
| 426 const base::TimeDelta wakeup_interval_; |
| 427 |
| 428 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherObserver); |
332 }; | 429 }; |
333 | 430 |
334 // Class for WatchDogThread and in its Init method, we start watching UI, IO, | 431 // Class for WatchDogThread and in its Init method, we start watching UI, IO, |
335 // DB, FILE, CACHED threads. | 432 // DB, FILE, CACHED threads. |
336 class WatchDogThread : public base::Thread { | 433 class WatchDogThread : public base::Thread { |
337 public: | 434 public: |
338 // Constructor. | 435 // Constructor. |
339 WatchDogThread(); | 436 WatchDogThread(); |
340 | 437 |
341 // Destroys the thread and stops the thread. | 438 // Destroys the thread and stops the thread. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 | 470 |
374 DISALLOW_COPY_AND_ASSIGN(WatchDogThread); | 471 DISALLOW_COPY_AND_ASSIGN(WatchDogThread); |
375 }; | 472 }; |
376 | 473 |
377 // DISABLE_RUNNABLE_METHOD_REFCOUNT is a convenience macro for disabling | 474 // DISABLE_RUNNABLE_METHOD_REFCOUNT is a convenience macro for disabling |
378 // refcounting of ThreadWatcher and ThreadWatcherList classes. | 475 // refcounting of ThreadWatcher and ThreadWatcherList classes. |
379 DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcher); | 476 DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcher); |
380 DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcherList); | 477 DISABLE_RUNNABLE_METHOD_REFCOUNT(ThreadWatcherList); |
381 | 478 |
382 #endif // CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ | 479 #endif // CHROME_BROWSER_METRICS_THREAD_WATCHER_H_ |
OLD | NEW |