Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / metrics / thread_watcher.h
blobb363370ed3bf0b09315343aabd46587fa4922b92
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
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
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
9 // all active ThreadWatcher objects.
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
13 // (difference between ping and pong times) as a histogram.
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
17 // then stack trace.
19 // Example Usage:
21 // The following is an example for watching responsiveness of watched (IO)
22 // thread. |sleep_time| specifies how often ping messages have to be sent to
23 // watched (IO) thread. |unresponsive_time| is the wait time after ping
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.
33 // base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(5);
34 // base::TimeDelta unresponsive_time = base::TimeDelta::FromSeconds(10);
35 // uint32 unresponsive_threshold = ThreadWatcherList::kUnresponsiveCount;
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);
42 #ifndef CHROME_BROWSER_METRICS_THREAD_WATCHER_H_
43 #define CHROME_BROWSER_METRICS_THREAD_WATCHER_H_
45 #include <map>
46 #include <string>
47 #include <vector>
49 #include "base/basictypes.h"
50 #include "base/command_line.h"
51 #include "base/gtest_prod_util.h"
52 #include "base/memory/ref_counted.h"
53 #include "base/memory/weak_ptr.h"
54 #include "base/message_loop/message_loop.h"
55 #include "base/metrics/histogram.h"
56 #include "base/profiler/stack_sampling_profiler.h"
57 #include "base/single_thread_task_runner.h"
58 #include "base/synchronization/lock.h"
59 #include "base/threading/platform_thread.h"
60 #include "base/threading/thread.h"
61 #include "base/threading/watchdog.h"
62 #include "base/time/time.h"
63 #include "components/omnibox/browser/omnibox_event_global_tracker.h"
64 #include "content/public/browser/browser_thread.h"
65 #include "content/public/browser/notification_observer.h"
66 #include "content/public/browser/notification_registrar.h"
68 class CustomThreadWatcher;
69 class StartupTimeBomb;
70 class ThreadWatcherList;
71 class ThreadWatcherObserver;
73 // This class performs health check on threads that would like to be watched.
74 class ThreadWatcher {
75 public:
76 // base::Bind supports methods with up to 6 parameters. WatchingParams is used
77 // as a workaround that limitation for invoking ThreadWatcher::StartWatching.
78 struct WatchingParams {
79 const content::BrowserThread::ID& thread_id;
80 const std::string& thread_name;
81 const base::TimeDelta& sleep_time;
82 const base::TimeDelta& unresponsive_time;
83 uint32 unresponsive_threshold;
84 bool crash_on_hang;
85 uint32 live_threads_threshold;
87 WatchingParams(const content::BrowserThread::ID& thread_id_in,
88 const std::string& thread_name_in,
89 const base::TimeDelta& sleep_time_in,
90 const base::TimeDelta& unresponsive_time_in,
91 uint32 unresponsive_threshold_in,
92 bool crash_on_hang_in,
93 uint32 live_threads_threshold_in)
94 : thread_id(thread_id_in),
95 thread_name(thread_name_in),
96 sleep_time(sleep_time_in),
97 unresponsive_time(unresponsive_time_in),
98 unresponsive_threshold(unresponsive_threshold_in),
99 crash_on_hang(crash_on_hang_in),
100 live_threads_threshold(live_threads_threshold_in) {
104 // This method starts performing health check on the given |thread_id|. It
105 // will create ThreadWatcher object for the given |thread_id|, |thread_name|.
106 // |sleep_time| is the wait time between ping messages. |unresponsive_time| is
107 // the wait time after ping message is sent, to check if we have received pong
108 // message or not. |unresponsive_threshold| is used to determine if the thread
109 // is responsive or not. The watched thread is considered unresponsive if it
110 // hasn't responded with a pong message for |unresponsive_threshold| number of
111 // ping messages. |crash_on_hang| specifies if browser should be crashed when
112 // the watched thread is unresponsive. |live_threads_threshold| specifies the
113 // number of browser threads that are to be responsive when we want to crash
114 // the browser and watched thread has become sufficiently unresponsive. It
115 // will register that ThreadWatcher object and activate the thread watching of
116 // the given thread_id.
117 static void StartWatching(const WatchingParams& params);
119 // Return the |thread_id_| of the thread being watched.
120 content::BrowserThread::ID thread_id() const { return thread_id_; }
122 // Return the name of the thread being watched.
123 std::string thread_name() const { return thread_name_; }
125 // Return the sleep time between ping messages to be sent to the thread.
126 base::TimeDelta sleep_time() const { return sleep_time_; }
128 // Return the the wait time to check the responsiveness of the thread.
129 base::TimeDelta unresponsive_time() const { return unresponsive_time_; }
131 // Returns true if we are montioring the thread.
132 bool active() const { return active_; }
134 // Returns |ping_time_| (used by unit tests).
135 base::TimeTicks ping_time() const { return ping_time_; }
137 // Returns |ping_sequence_number_| (used by unit tests).
138 uint64 ping_sequence_number() const { return ping_sequence_number_; }
140 protected:
141 // Construct a ThreadWatcher for the given |thread_id|. |sleep_time| is the
142 // wait time between ping messages. |unresponsive_time| is the wait time after
143 // ping message is sent, to check if we have received pong message or not.
144 explicit ThreadWatcher(const WatchingParams& params);
146 virtual ~ThreadWatcher();
148 // This method activates the thread watching which starts ping/pong messaging.
149 virtual void ActivateThreadWatching();
151 // This method de-activates the thread watching and revokes all tasks.
152 virtual void DeActivateThreadWatching();
154 // This will ensure that the watching is actively taking place, and awaken
155 // (i.e., post a PostPingMessage()) if the watcher has stopped pinging due to
156 // lack of user activity. It will also reset |ping_count_| to
157 // |unresponsive_threshold_|.
158 virtual void WakeUp();
160 // This method records when ping message was sent and it will Post a task
161 // (OnPingMessage()) to the watched thread that does nothing but respond with
162 // OnPongMessage(). It also posts a task (OnCheckResponsiveness()) to check
163 // responsiveness of monitored thread that would be called after waiting
164 // |unresponsive_time_|.
165 // This method is accessible on WatchDogThread.
166 virtual void PostPingMessage();
168 // This method handles a Pong Message from watched thread. It will track the
169 // response time (pong time minus ping time) via histograms. It posts a
170 // PostPingMessage() task that would be called after waiting |sleep_time_|. It
171 // increments |ping_sequence_number_| by 1.
172 // This method is accessible on WatchDogThread.
173 virtual void OnPongMessage(uint64 ping_sequence_number);
175 // This method will determine if the watched thread is responsive or not. If
176 // the latest |ping_sequence_number_| is not same as the
177 // |ping_sequence_number| that is passed in, then we can assume that watched
178 // thread has responded with a pong message.
179 // This method is accessible on WatchDogThread.
180 virtual void OnCheckResponsiveness(uint64 ping_sequence_number);
182 // Set by OnCheckResponsiveness when it determines if the watched thread is
183 // responsive or not.
184 bool responsive_;
186 private:
187 friend class ThreadWatcherList;
188 friend class CustomThreadWatcher;
190 // Allow tests to access our innards for testing purposes.
191 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, Registration);
192 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadResponding);
193 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadNotResponding);
194 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsResponding);
195 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, MultipleThreadsNotResponding);
197 // Post constructor initialization.
198 void Initialize();
200 // Watched thread does nothing except post callback_task to the WATCHDOG
201 // Thread. This method is called on watched thread.
202 static void OnPingMessage(const content::BrowserThread::ID& thread_id,
203 const base::Closure& callback_task);
205 // This method resets |unresponsive_count_| to zero because watched thread is
206 // responding to the ping message with a pong message.
207 void ResetHangCounters();
209 // This method records watched thread is not responding to the ping message.
210 // It increments |unresponsive_count_| by 1.
211 void GotNoResponse();
213 // This method returns true if the watched thread has not responded with a
214 // pong message for |unresponsive_threshold_| number of ping messages.
215 bool IsVeryUnresponsive();
217 // The |thread_id_| of the thread being watched. Only one instance can exist
218 // for the given |thread_id_| of the thread being watched.
219 const content::BrowserThread::ID thread_id_;
221 // The name of the thread being watched.
222 const std::string thread_name_;
224 // Used to post messages to watched thread.
225 scoped_refptr<base::SingleThreadTaskRunner> watched_runner_;
227 // It is the sleep time between the receipt of a pong message back, and the
228 // sending of another ping message.
229 const base::TimeDelta sleep_time_;
231 // It is the duration from sending a ping message, until we check status to be
232 // sure a pong message has been returned.
233 const base::TimeDelta unresponsive_time_;
235 // This is the last time when ping message was sent.
236 base::TimeTicks ping_time_;
238 // This is the last time when we got pong message.
239 base::TimeTicks pong_time_;
241 // This is the sequence number of the next ping for which there is no pong. If
242 // the instance is sleeping, then it will be the sequence number for the next
243 // ping.
244 uint64 ping_sequence_number_;
246 // This is set to true if thread watcher is watching.
247 bool active_;
249 // The counter tracks least number of ping messages that will be sent to
250 // watched thread before the ping-pong mechanism will go into an extended
251 // sleep. If this value is zero, then the mechanism is in an extended sleep,
252 // and awaiting some observed user action before continuing.
253 int ping_count_;
255 // Histogram that keeps track of response times for the watched thread.
256 base::HistogramBase* response_time_histogram_;
258 // Histogram that keeps track of unresponsive time since the last pong message
259 // when we got no response (GotNoResponse()) from the watched thread.
260 base::HistogramBase* unresponsive_time_histogram_;
262 // Histogram that keeps track of how many threads are responding when we got
263 // no response (GotNoResponse()) from the watched thread.
264 base::HistogramBase* responsive_count_histogram_;
266 // Histogram that keeps track of how many threads are not responding when we
267 // got no response (GotNoResponse()) from the watched thread. Count includes
268 // the thread that got no response.
269 base::HistogramBase* unresponsive_count_histogram_;
271 // This counter tracks the unresponsiveness of watched thread. If this value
272 // is zero then watched thread has responded with a pong message. This is
273 // incremented by 1 when we got no response (GotNoResponse()) from the watched
274 // thread.
275 uint32 unresponsive_count_;
277 // This is set to true when we would have crashed the browser because the
278 // watched thread hasn't responded at least |unresponsive_threshold_| times.
279 // It is reset to false when watched thread responds with a pong message.
280 bool hung_processing_complete_;
282 // This is used to determine if the watched thread is responsive or not. If
283 // watched thread's |unresponsive_count_| is greater than or equal to
284 // |unresponsive_threshold_| then we would consider it as unresponsive.
285 uint32 unresponsive_threshold_;
287 // This is set to true if we want to crash the browser when the watched thread
288 // has become sufficiently unresponsive, while other threads are sufficiently
289 // responsive.
290 bool crash_on_hang_;
292 // This specifies the number of browser threads that are to be responsive when
293 // we want to crash the browser because watched thread has become sufficiently
294 // unresponsive.
295 uint32 live_threads_threshold_;
297 // We use this factory to create callback tasks for ThreadWatcher object. We
298 // use this during ping-pong messaging between WatchDog thread and watched
299 // thread.
300 base::WeakPtrFactory<ThreadWatcher> weak_ptr_factory_;
302 DISALLOW_COPY_AND_ASSIGN(ThreadWatcher);
305 // Class with a list of all active thread watchers. A thread watcher is active
306 // if it has been registered, which includes determing the histogram name. This
307 // class provides utility functions to start and stop watching all browser
308 // threads. Only one instance of this class exists.
309 class ThreadWatcherList {
310 public:
311 // A map from BrowserThread to the actual instances.
312 typedef std::map<content::BrowserThread::ID, ThreadWatcher*> RegistrationList;
314 // A map from thread names (UI, IO, etc) to |CrashDataThresholds|.
315 // |live_threads_threshold| specifies the maximum number of browser threads
316 // that have to be responsive when we want to crash the browser because of
317 // hung watched thread. This threshold allows us to either look for a system
318 // deadlock, or look for a solo hung thread. A small live_threads_threshold
319 // looks for a broad deadlock (few browser threads left running), and a large
320 // threshold looks for a single hung thread (this in only appropriate for a
321 // thread that *should* never have much jank, such as the IO).
323 // |unresponsive_threshold| specifies the number of unanswered ping messages
324 // after which watched (UI, IO, etc) thread is considered as not responsive.
325 // We translate "time" (given in seconds) into a number of pings. As a result,
326 // we only declare a thread unresponsive when a lot of "time" has passed (many
327 // pings), and yet our pinging thread has continued to process messages (so we
328 // know the entire PC is not hung). Set this number higher to crash less
329 // often, and lower to crash more often.
331 // The map lists all threads (by name) that can induce a crash by hanging. It
332 // is populated from the command line, or given a default list. See
333 // InitializeAndStartWatching() for the separate list of all threads that are
334 // watched, as they provide the system context of how hung *other* threads
335 // are.
337 // ThreadWatcher monitors five browser threads (i.e., UI, IO, DB, FILE,
338 // and CACHE). Out of the 5 threads, any subset may be watched, to potentially
339 // cause a crash. The following example's command line causes exactly 3
340 // threads to be watched.
342 // The example command line argument consists of "UI:3:18,IO:3:18,FILE:5:90".
343 // In that string, the first parameter specifies the thread_id: UI, IO or
344 // FILE. The second parameter specifies |live_threads_threshold|. For UI and
345 // IO threads, we would crash if the number of threads responding is less than
346 // or equal to 3. The third parameter specifies the unresponsive threshold
347 // seconds. This number is used to calculate |unresponsive_threshold|. In this
348 // example for UI and IO threads, we would crash if those threads don't
349 // respond for 18 seconds (or 9 unanswered ping messages) and for FILE thread,
350 // crash_seconds is set to 90 seconds (or 45 unanswered ping messages).
352 // The following examples explain how the data in |CrashDataThresholds|
353 // controls the crashes.
355 // Example 1: If the |live_threads_threshold| value for "IO" was 3 and
356 // unresponsive threshold seconds is 18 (or |unresponsive_threshold| is 9),
357 // then we would crash if the IO thread was hung (9 unanswered ping messages)
358 // and if at least one thread is responding and total responding threads is
359 // less than or equal to 3 (this thread, plus at least one other thread is
360 // unresponsive). We would not crash if none of the threads are responding, as
361 // we'd assume such large hang counts mean that the system is generally
362 // unresponsive.
363 // Example 2: If the |live_threads_threshold| value for "UI" was any number
364 // higher than 6 and unresponsive threshold seconds is 18 (or
365 // |unresponsive_threshold| is 9), then we would always crash if the UI thread
366 // was hung (9 unanswered ping messages), no matter what the other threads are
367 // doing.
368 // Example 3: If the |live_threads_threshold| value of "FILE" was 5 and
369 // unresponsive threshold seconds is 90 (or |unresponsive_threshold| is 45),
370 // then we would only crash if the FILE thread was the ONLY hung thread
371 // (because we watch 6 threads). If there was another unresponsive thread, we
372 // would not consider this a problem worth crashing for. FILE thread would be
373 // considered as hung if it didn't respond for 45 ping messages.
374 struct CrashDataThresholds {
375 CrashDataThresholds(uint32 live_threads_threshold,
376 uint32 unresponsive_threshold);
377 CrashDataThresholds();
379 uint32 live_threads_threshold;
380 uint32 unresponsive_threshold;
382 typedef std::map<std::string, CrashDataThresholds> CrashOnHangThreadMap;
384 // This method posts a task on WatchDogThread to start watching all browser
385 // threads.
386 // This method is accessible on UI thread.
387 static void StartWatchingAll(const base::CommandLine& command_line);
389 // This method posts a task on WatchDogThread to RevokeAll tasks and to
390 // deactive thread watching of other threads and tell NotificationService to
391 // stop calling Observe.
392 // This method is accessible on UI thread.
393 static void StopWatchingAll();
395 // Register() stores a pointer to the given ThreadWatcher in a global map.
396 static void Register(ThreadWatcher* watcher);
398 // This method returns true if the ThreadWatcher object is registerd.
399 static bool IsRegistered(const content::BrowserThread::ID thread_id);
401 // This method returns number of responsive and unresponsive watched threads.
402 static void GetStatusOfThreads(uint32* responding_thread_count,
403 uint32* unresponding_thread_count);
405 // This will ensure that the watching is actively taking place, and awaken
406 // all thread watchers that are registered.
407 static void WakeUpAll();
409 private:
410 // Allow tests to access our innards for testing purposes.
411 friend class CustomThreadWatcher;
412 friend class ThreadWatcherListTest;
413 friend class ThreadWatcherTest;
414 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherAndroidTest,
415 ApplicationStatusNotification);
416 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherListTest, Restart);
417 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadNamesOnlyArgs);
418 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, ThreadNamesAndLiveThresholdArgs);
419 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, CrashOnHangThreadsAllArgs);
421 // This singleton holds the global list of registered ThreadWatchers.
422 ThreadWatcherList();
424 // Destructor deletes all registered ThreadWatcher instances.
425 virtual ~ThreadWatcherList();
427 // Parses the command line to get |crash_on_hang_threads| map from
428 // switches::kCrashOnHangThreads. |crash_on_hang_threads| is a map of
429 // |crash_on_hang| thread's names to |CrashDataThresholds|.
430 static void ParseCommandLine(
431 const base::CommandLine& command_line,
432 uint32* unresponsive_threshold,
433 CrashOnHangThreadMap* crash_on_hang_threads);
435 // Parses the argument |crash_on_hang_thread_names| and creates
436 // |crash_on_hang_threads| map of |crash_on_hang| thread's names to
437 // |CrashDataThresholds|. If |crash_on_hang_thread_names| doesn't specify
438 // |live_threads_threshold|, then it uses |default_live_threads_threshold| as
439 // the value. If |crash_on_hang_thread_names| doesn't specify |crash_seconds|,
440 // then it uses |default_crash_seconds| as the value.
441 static void ParseCommandLineCrashOnHangThreads(
442 const std::string& crash_on_hang_thread_names,
443 uint32 default_live_threads_threshold,
444 uint32 default_crash_seconds,
445 CrashOnHangThreadMap* crash_on_hang_threads);
447 // This constructs the |ThreadWatcherList| singleton and starts watching
448 // browser threads by calling StartWatching() on each browser thread that is
449 // watched. It disarms StartupTimeBomb.
450 static void InitializeAndStartWatching(
451 uint32 unresponsive_threshold,
452 const CrashOnHangThreadMap& crash_on_hang_threads);
454 // This method calls ThreadWatcher::StartWatching() to perform health check on
455 // the given |thread_id|.
456 static void StartWatching(
457 const content::BrowserThread::ID& thread_id,
458 const std::string& thread_name,
459 const base::TimeDelta& sleep_time,
460 const base::TimeDelta& unresponsive_time,
461 uint32 unresponsive_threshold,
462 const CrashOnHangThreadMap& crash_on_hang_threads);
464 // Delete all thread watcher objects and remove them from global map. It also
465 // deletes |g_thread_watcher_list_|.
466 static void DeleteAll();
468 // The Find() method can be used to test to see if a given ThreadWatcher was
469 // already registered, or to retrieve a pointer to it from the global map.
470 static ThreadWatcher* Find(const content::BrowserThread::ID& thread_id);
472 // Sets |g_stopped_| on the WatchDogThread. This is necessary to reflect the
473 // state between the delayed |StartWatchingAll| and the immediate
474 // |StopWatchingAll|.
475 static void SetStopped(bool stopped);
477 // The singleton of this class and is used to keep track of information about
478 // threads that are being watched.
479 static ThreadWatcherList* g_thread_watcher_list_;
481 // StartWatchingAll() is delayed in relation to StopWatchingAll(), so if
482 // a Stop comes first, prevent further initialization.
483 static bool g_stopped_;
485 // This is the wait time between ping messages.
486 static const int kSleepSeconds;
488 // This is the wait time after ping message is sent, to check if we have
489 // received pong message or not.
490 static const int kUnresponsiveSeconds;
492 // Default values for |unresponsive_threshold|.
493 static const int kUnresponsiveCount;
495 // Default values for |live_threads_threshold|.
496 static const int kLiveThreadsThreshold;
498 // Default value for the delay until |InitializeAndStartWatching| is called.
499 // Non-const for tests.
500 static int g_initialize_delay_seconds;
502 // Map of all registered watched threads, from thread_id to ThreadWatcher.
503 RegistrationList registered_;
505 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList);
508 // This class ensures that the thread watching is actively taking place. Only
509 // one instance of this class exists.
510 class ThreadWatcherObserver : public content::NotificationObserver {
511 public:
512 // Registers |g_thread_watcher_observer_| as the Notifications observer.
513 // |wakeup_interval| specifies how often to wake up thread watchers. This
514 // method is accessible on UI thread.
515 static void SetupNotifications(const base::TimeDelta& wakeup_interval);
517 // Removes all ints from |registrar_| and deletes
518 // |g_thread_watcher_observer_|. This method is accessible on UI thread.
519 static void RemoveNotifications();
521 private:
522 // Constructor of |g_thread_watcher_observer_| singleton.
523 explicit ThreadWatcherObserver(const base::TimeDelta& wakeup_interval);
525 // Destructor of |g_thread_watcher_observer_| singleton.
526 ~ThreadWatcherObserver() override;
528 // This ensures all thread watchers are active because there is some user
529 // activity. It will wake up all thread watchers every |wakeup_interval_|
530 // seconds. This is the implementation of content::NotificationObserver. When
531 // a matching notification is posted to the notification service, this method
532 // is called.
533 void Observe(int type,
534 const content::NotificationSource& source,
535 const content::NotificationDetails& details) override;
537 // Called when a URL is opened from the Omnibox.
538 void OnURLOpenedFromOmnibox(OmniboxLog* log);
540 // Called when user activity is detected.
541 void OnUserActivityDetected();
543 // The singleton of this class.
544 static ThreadWatcherObserver* g_thread_watcher_observer_;
546 // The registrar that holds ints to be observed.
547 content::NotificationRegistrar registrar_;
549 // This is the last time when woke all thread watchers up.
550 base::TimeTicks last_wakeup_time_;
552 // It is the time interval between wake up calls to thread watchers.
553 const base::TimeDelta wakeup_interval_;
555 // Subscription for receiving callbacks that a URL was opened from the
556 // omnibox.
557 scoped_ptr<base::CallbackList<void(OmniboxLog*)>::Subscription>
558 omnibox_url_opened_subscription_;
560 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherObserver);
563 // Class for WatchDogThread and in its Init method, we start watching UI, IO,
564 // DB, FILE, CACHED threads.
565 class WatchDogThread : public base::Thread {
566 public:
567 // Constructor.
568 WatchDogThread();
570 // Destroys the thread and stops the thread.
571 ~WatchDogThread() override;
573 // Callable on any thread. Returns whether you're currently on a
574 // WatchDogThread.
575 static bool CurrentlyOnWatchDogThread();
577 // These are the same methods in message_loop.h, but are guaranteed to either
578 // get posted to the MessageLoop if it's still alive, or be deleted otherwise.
579 // They return true iff the watchdog thread existed and the task was posted.
580 // Note that even if the task is posted, there's no guarantee that it will
581 // run, since the target thread may already have a Quit message in its queue.
582 static bool PostTask(const tracked_objects::Location& from_here,
583 const base::Closure& task);
584 static bool PostDelayedTask(const tracked_objects::Location& from_here,
585 const base::Closure& task,
586 base::TimeDelta delay);
588 protected:
589 void Init() override;
590 void CleanUp() override;
592 private:
593 friend class JankTimeBombTest;
595 // This method returns true if Init() is called.
596 bool Started() const;
598 static bool PostTaskHelper(
599 const tracked_objects::Location& from_here,
600 const base::Closure& task,
601 base::TimeDelta delay);
603 DISALLOW_COPY_AND_ASSIGN(WatchDogThread);
606 // This is a wrapper class for getting the crash dumps of the hangs during
607 // startup.
608 class StartupTimeBomb {
609 public:
610 // This singleton is instantiated when the browser process is launched.
611 StartupTimeBomb();
613 // Destructor disarm's startup_watchdog_ (if it is arm'ed) so that alarm
614 // doesn't go off.
615 ~StartupTimeBomb();
617 // Constructs |startup_watchdog_| which spawns a thread and starts timer.
618 // |duration| specifies how long |startup_watchdog_| will wait before it
619 // calls alarm.
620 void Arm(const base::TimeDelta& duration);
622 // Disarms |startup_watchdog_| thread and then deletes it which stops the
623 // Watchdog thread.
624 void Disarm();
626 // Disarms |g_startup_timebomb_|.
627 static void DisarmStartupTimeBomb();
629 private:
630 // Deletes |startup_watchdog_| if it is joinable. If |startup_watchdog_| is
631 // not joinable, then it will post a delayed task to try again.
632 void DeleteStartupWatchdog();
634 // The singleton of this class.
635 static StartupTimeBomb* g_startup_timebomb_;
637 // Watches for hangs during startup until it is disarm'ed.
638 base::Watchdog* startup_watchdog_;
640 // The |thread_id_| on which this object is constructed.
641 const base::PlatformThreadId thread_id_;
643 DISALLOW_COPY_AND_ASSIGN(StartupTimeBomb);
646 // This is a wrapper class for metrics logging of the stack of a janky method.
647 class JankTimeBomb {
648 public:
649 // This is instantiated when the jank needs to be detected in a method. Posts
650 // an Alarm callback task on WatchDogThread with |duration| as the delay. This
651 // can be called on any thread.
652 explicit JankTimeBomb(base::TimeDelta duration);
653 virtual ~JankTimeBomb();
655 // Returns true if JankTimeBomb is enabled.
656 bool IsEnabled() const;
658 protected:
659 // Logs the call stack of given thread_id's janky method. This runs on
660 // WatchDogThread. This is overridden in tests to prevent the metrics logging.
661 virtual void Alarm(base::PlatformThreadId thread_id);
663 private:
664 // A profiler that periodically samples stack traces. Used to sample jank
665 // behavior.
666 scoped_ptr<base::StackSamplingProfiler> sampling_profiler_;
668 // We use this factory during creation and starting timer.
669 base::WeakPtrFactory<JankTimeBomb> weak_ptr_factory_;
671 DISALLOW_COPY_AND_ASSIGN(JankTimeBomb);
674 // This is a wrapper class for detecting hangs during shutdown.
675 class ShutdownWatcherHelper {
676 public:
677 // Create an empty holder for |shutdown_watchdog_|.
678 ShutdownWatcherHelper();
680 // Destructor disarm's shutdown_watchdog_ so that alarm doesn't go off.
681 ~ShutdownWatcherHelper();
683 // Constructs ShutdownWatchDogThread which spawns a thread and starts timer.
684 // |duration| specifies how long it will wait before it calls alarm.
685 void Arm(const base::TimeDelta& duration);
687 private:
688 // shutdown_watchdog_ watches for hangs during shutdown.
689 base::Watchdog* shutdown_watchdog_;
691 // The |thread_id_| on which this object is constructed.
692 const base::PlatformThreadId thread_id_;
694 DISALLOW_COPY_AND_ASSIGN(ShutdownWatcherHelper);
697 #endif // CHROME_BROWSER_METRICS_THREAD_WATCHER_H_