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
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_
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/single_thread_task_runner.h"
57 #include "base/synchronization/lock.h"
58 #include "base/threading/platform_thread.h"
59 #include "base/threading/thread.h"
60 #include "base/threading/watchdog.h"
61 #include "base/time/time.h"
62 #include "components/omnibox/browser/omnibox_event_global_tracker.h"
63 #include "content/public/browser/browser_thread.h"
64 #include "content/public/browser/notification_observer.h"
65 #include "content/public/browser/notification_registrar.h"
67 class CustomThreadWatcher
;
68 class StartupTimeBomb
;
69 class ThreadWatcherList
;
70 class ThreadWatcherObserver
;
72 // This class performs health check on threads that would like to be watched.
75 // base::Bind supports methods with up to 6 parameters. WatchingParams is used
76 // as a workaround that limitation for invoking ThreadWatcher::StartWatching.
77 struct WatchingParams
{
78 const content::BrowserThread::ID
& thread_id
;
79 const std::string
& thread_name
;
80 const base::TimeDelta
& sleep_time
;
81 const base::TimeDelta
& unresponsive_time
;
82 uint32 unresponsive_threshold
;
84 uint32 live_threads_threshold
;
86 WatchingParams(const content::BrowserThread::ID
& thread_id_in
,
87 const std::string
& thread_name_in
,
88 const base::TimeDelta
& sleep_time_in
,
89 const base::TimeDelta
& unresponsive_time_in
,
90 uint32 unresponsive_threshold_in
,
91 bool crash_on_hang_in
,
92 uint32 live_threads_threshold_in
)
93 : thread_id(thread_id_in
),
94 thread_name(thread_name_in
),
95 sleep_time(sleep_time_in
),
96 unresponsive_time(unresponsive_time_in
),
97 unresponsive_threshold(unresponsive_threshold_in
),
98 crash_on_hang(crash_on_hang_in
),
99 live_threads_threshold(live_threads_threshold_in
) {
103 // This method starts performing health check on the given |thread_id|. It
104 // will create ThreadWatcher object for the given |thread_id|, |thread_name|.
105 // |sleep_time| is the wait time between ping messages. |unresponsive_time| is
106 // the wait time after ping message is sent, to check if we have received pong
107 // message or not. |unresponsive_threshold| is used to determine if the thread
108 // is responsive or not. The watched thread is considered unresponsive if it
109 // hasn't responded with a pong message for |unresponsive_threshold| number of
110 // ping messages. |crash_on_hang| specifies if browser should be crashed when
111 // the watched thread is unresponsive. |live_threads_threshold| specifies the
112 // number of browser threads that are to be responsive when we want to crash
113 // the browser and watched thread has become sufficiently unresponsive. It
114 // will register that ThreadWatcher object and activate the thread watching of
115 // the given thread_id.
116 static void StartWatching(const WatchingParams
& params
);
118 // Return the |thread_id_| of the thread being watched.
119 content::BrowserThread::ID
thread_id() const { return thread_id_
; }
121 // Return the name of the thread being watched.
122 std::string
thread_name() const { return thread_name_
; }
124 // Return the sleep time between ping messages to be sent to the thread.
125 base::TimeDelta
sleep_time() const { return sleep_time_
; }
127 // Return the the wait time to check the responsiveness of the thread.
128 base::TimeDelta
unresponsive_time() const { return unresponsive_time_
; }
130 // Returns true if we are montioring the thread.
131 bool active() const { return active_
; }
133 // Returns |ping_time_| (used by unit tests).
134 base::TimeTicks
ping_time() const { return ping_time_
; }
136 // Returns |ping_sequence_number_| (used by unit tests).
137 uint64
ping_sequence_number() const { return ping_sequence_number_
; }
140 // Construct a ThreadWatcher for the given |thread_id|. |sleep_time| is the
141 // wait time between ping messages. |unresponsive_time| is the wait time after
142 // ping message is sent, to check if we have received pong message or not.
143 explicit ThreadWatcher(const WatchingParams
& params
);
145 virtual ~ThreadWatcher();
147 // This method activates the thread watching which starts ping/pong messaging.
148 virtual void ActivateThreadWatching();
150 // This method de-activates the thread watching and revokes all tasks.
151 virtual void DeActivateThreadWatching();
153 // This will ensure that the watching is actively taking place, and awaken
154 // (i.e., post a PostPingMessage()) if the watcher has stopped pinging due to
155 // lack of user activity. It will also reset |ping_count_| to
156 // |unresponsive_threshold_|.
157 virtual void WakeUp();
159 // This method records when ping message was sent and it will Post a task
160 // (OnPingMessage()) to the watched thread that does nothing but respond with
161 // OnPongMessage(). It also posts a task (OnCheckResponsiveness()) to check
162 // responsiveness of monitored thread that would be called after waiting
163 // |unresponsive_time_|.
164 // This method is accessible on WatchDogThread.
165 virtual void PostPingMessage();
167 // This method handles a Pong Message from watched thread. It will track the
168 // response time (pong time minus ping time) via histograms. It posts a
169 // PostPingMessage() task that would be called after waiting |sleep_time_|. It
170 // increments |ping_sequence_number_| by 1.
171 // This method is accessible on WatchDogThread.
172 virtual void OnPongMessage(uint64 ping_sequence_number
);
174 // This method will determine if the watched thread is responsive or not. If
175 // the latest |ping_sequence_number_| is not same as the
176 // |ping_sequence_number| that is passed in, then we can assume that watched
177 // thread has responded with a pong message.
178 // This method is accessible on WatchDogThread.
179 virtual void OnCheckResponsiveness(uint64 ping_sequence_number
);
181 // Set by OnCheckResponsiveness when it determines if the watched thread is
182 // responsive or not.
186 friend class ThreadWatcherList
;
187 friend class CustomThreadWatcher
;
189 // Allow tests to access our innards for testing purposes.
190 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, Registration
);
191 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, ThreadResponding
);
192 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, ThreadNotResponding
);
193 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, MultipleThreadsResponding
);
194 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, MultipleThreadsNotResponding
);
196 // Post constructor initialization.
199 // Watched thread does nothing except post callback_task to the WATCHDOG
200 // Thread. This method is called on watched thread.
201 static void OnPingMessage(const content::BrowserThread::ID
& thread_id
,
202 const base::Closure
& callback_task
);
204 // This method resets |unresponsive_count_| to zero because watched thread is
205 // responding to the ping message with a pong message.
206 void ResetHangCounters();
208 // This method records watched thread is not responding to the ping message.
209 // It increments |unresponsive_count_| by 1.
210 void GotNoResponse();
212 // This method returns true if the watched thread has not responded with a
213 // pong message for |unresponsive_threshold_| number of ping messages.
214 bool IsVeryUnresponsive();
216 // The |thread_id_| of the thread being watched. Only one instance can exist
217 // for the given |thread_id_| of the thread being watched.
218 const content::BrowserThread::ID thread_id_
;
220 // The name of the thread being watched.
221 const std::string thread_name_
;
223 // Used to post messages to watched thread.
224 scoped_refptr
<base::SingleThreadTaskRunner
> watched_runner_
;
226 // It is the sleep time between the receipt of a pong message back, and the
227 // sending of another ping message.
228 const base::TimeDelta sleep_time_
;
230 // It is the duration from sending a ping message, until we check status to be
231 // sure a pong message has been returned.
232 const base::TimeDelta unresponsive_time_
;
234 // This is the last time when ping message was sent.
235 base::TimeTicks ping_time_
;
237 // This is the last time when we got pong message.
238 base::TimeTicks pong_time_
;
240 // This is the sequence number of the next ping for which there is no pong. If
241 // the instance is sleeping, then it will be the sequence number for the next
243 uint64 ping_sequence_number_
;
245 // This is set to true if thread watcher is watching.
248 // The counter tracks least number of ping messages that will be sent to
249 // watched thread before the ping-pong mechanism will go into an extended
250 // sleep. If this value is zero, then the mechanism is in an extended sleep,
251 // and awaiting some observed user action before continuing.
254 // Histogram that keeps track of response times for the watched thread.
255 base::HistogramBase
* response_time_histogram_
;
257 // Histogram that keeps track of unresponsive time since the last pong message
258 // when we got no response (GotNoResponse()) from the watched thread.
259 base::HistogramBase
* unresponsive_time_histogram_
;
261 // Histogram that keeps track of how many threads are responding when we got
262 // no response (GotNoResponse()) from the watched thread.
263 base::HistogramBase
* responsive_count_histogram_
;
265 // Histogram that keeps track of how many threads are not responding when we
266 // got no response (GotNoResponse()) from the watched thread. Count includes
267 // the thread that got no response.
268 base::HistogramBase
* unresponsive_count_histogram_
;
270 // This counter tracks the unresponsiveness of watched thread. If this value
271 // is zero then watched thread has responded with a pong message. This is
272 // incremented by 1 when we got no response (GotNoResponse()) from the watched
274 uint32 unresponsive_count_
;
276 // This is set to true when we would have crashed the browser because the
277 // watched thread hasn't responded at least |unresponsive_threshold_| times.
278 // It is reset to false when watched thread responds with a pong message.
279 bool hung_processing_complete_
;
281 // This is used to determine if the watched thread is responsive or not. If
282 // watched thread's |unresponsive_count_| is greater than or equal to
283 // |unresponsive_threshold_| then we would consider it as unresponsive.
284 uint32 unresponsive_threshold_
;
286 // This is set to true if we want to crash the browser when the watched thread
287 // has become sufficiently unresponsive, while other threads are sufficiently
291 // This specifies the number of browser threads that are to be responsive when
292 // we want to crash the browser because watched thread has become sufficiently
294 uint32 live_threads_threshold_
;
296 // We use this factory to create callback tasks for ThreadWatcher object. We
297 // use this during ping-pong messaging between WatchDog thread and watched
299 base::WeakPtrFactory
<ThreadWatcher
> weak_ptr_factory_
;
301 DISALLOW_COPY_AND_ASSIGN(ThreadWatcher
);
304 // Class with a list of all active thread watchers. A thread watcher is active
305 // if it has been registered, which includes determing the histogram name. This
306 // class provides utility functions to start and stop watching all browser
307 // threads. Only one instance of this class exists.
308 class ThreadWatcherList
{
310 // A map from BrowserThread to the actual instances.
311 typedef std::map
<content::BrowserThread::ID
, ThreadWatcher
*> RegistrationList
;
313 // A map from thread names (UI, IO, etc) to |CrashDataThresholds|.
314 // |live_threads_threshold| specifies the maximum number of browser threads
315 // that have to be responsive when we want to crash the browser because of
316 // hung watched thread. This threshold allows us to either look for a system
317 // deadlock, or look for a solo hung thread. A small live_threads_threshold
318 // looks for a broad deadlock (few browser threads left running), and a large
319 // threshold looks for a single hung thread (this in only appropriate for a
320 // thread that *should* never have much jank, such as the IO).
322 // |unresponsive_threshold| specifies the number of unanswered ping messages
323 // after which watched (UI, IO, etc) thread is considered as not responsive.
324 // We translate "time" (given in seconds) into a number of pings. As a result,
325 // we only declare a thread unresponsive when a lot of "time" has passed (many
326 // pings), and yet our pinging thread has continued to process messages (so we
327 // know the entire PC is not hung). Set this number higher to crash less
328 // often, and lower to crash more often.
330 // The map lists all threads (by name) that can induce a crash by hanging. It
331 // is populated from the command line, or given a default list. See
332 // InitializeAndStartWatching() for the separate list of all threads that are
333 // watched, as they provide the system context of how hung *other* threads
336 // ThreadWatcher monitors five browser threads (i.e., UI, IO, DB, FILE,
337 // and CACHE). Out of the 5 threads, any subset may be watched, to potentially
338 // cause a crash. The following example's command line causes exactly 3
339 // threads to be watched.
341 // The example command line argument consists of "UI:3:18,IO:3:18,FILE:5:90".
342 // In that string, the first parameter specifies the thread_id: UI, IO or
343 // FILE. The second parameter specifies |live_threads_threshold|. For UI and
344 // IO threads, we would crash if the number of threads responding is less than
345 // or equal to 3. The third parameter specifies the unresponsive threshold
346 // seconds. This number is used to calculate |unresponsive_threshold|. In this
347 // example for UI and IO threads, we would crash if those threads don't
348 // respond for 18 seconds (or 9 unanswered ping messages) and for FILE thread,
349 // crash_seconds is set to 90 seconds (or 45 unanswered ping messages).
351 // The following examples explain how the data in |CrashDataThresholds|
352 // controls the crashes.
354 // Example 1: If the |live_threads_threshold| value for "IO" was 3 and
355 // unresponsive threshold seconds is 18 (or |unresponsive_threshold| is 9),
356 // then we would crash if the IO thread was hung (9 unanswered ping messages)
357 // and if at least one thread is responding and total responding threads is
358 // less than or equal to 3 (this thread, plus at least one other thread is
359 // unresponsive). We would not crash if none of the threads are responding, as
360 // we'd assume such large hang counts mean that the system is generally
362 // Example 2: If the |live_threads_threshold| value for "UI" was any number
363 // higher than 6 and unresponsive threshold seconds is 18 (or
364 // |unresponsive_threshold| is 9), then we would always crash if the UI thread
365 // was hung (9 unanswered ping messages), no matter what the other threads are
367 // Example 3: If the |live_threads_threshold| value of "FILE" was 5 and
368 // unresponsive threshold seconds is 90 (or |unresponsive_threshold| is 45),
369 // then we would only crash if the FILE thread was the ONLY hung thread
370 // (because we watch 6 threads). If there was another unresponsive thread, we
371 // would not consider this a problem worth crashing for. FILE thread would be
372 // considered as hung if it didn't respond for 45 ping messages.
373 struct CrashDataThresholds
{
374 CrashDataThresholds(uint32 live_threads_threshold
,
375 uint32 unresponsive_threshold
);
376 CrashDataThresholds();
378 uint32 live_threads_threshold
;
379 uint32 unresponsive_threshold
;
381 typedef std::map
<std::string
, CrashDataThresholds
> CrashOnHangThreadMap
;
383 // This method posts a task on WatchDogThread to start watching all browser
385 // This method is accessible on UI thread.
386 static void StartWatchingAll(const base::CommandLine
& command_line
);
388 // This method posts a task on WatchDogThread to RevokeAll tasks and to
389 // deactive thread watching of other threads and tell NotificationService to
390 // stop calling Observe.
391 // This method is accessible on UI thread.
392 static void StopWatchingAll();
394 // Register() stores a pointer to the given ThreadWatcher in a global map.
395 static void Register(ThreadWatcher
* watcher
);
397 // This method returns true if the ThreadWatcher object is registerd.
398 static bool IsRegistered(const content::BrowserThread::ID thread_id
);
400 // This method returns number of responsive and unresponsive watched threads.
401 static void GetStatusOfThreads(uint32
* responding_thread_count
,
402 uint32
* unresponding_thread_count
);
404 // This will ensure that the watching is actively taking place, and awaken
405 // all thread watchers that are registered.
406 static void WakeUpAll();
409 // Allow tests to access our innards for testing purposes.
410 friend class CustomThreadWatcher
;
411 friend class ThreadWatcherListTest
;
412 friend class ThreadWatcherTest
;
413 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherAndroidTest
,
414 ApplicationStatusNotification
);
415 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherListTest
, Restart
);
416 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, ThreadNamesOnlyArgs
);
417 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, ThreadNamesAndLiveThresholdArgs
);
418 FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest
, CrashOnHangThreadsAllArgs
);
420 // This singleton holds the global list of registered ThreadWatchers.
423 // Destructor deletes all registered ThreadWatcher instances.
424 virtual ~ThreadWatcherList();
426 // Parses the command line to get |crash_on_hang_threads| map from
427 // switches::kCrashOnHangThreads. |crash_on_hang_threads| is a map of
428 // |crash_on_hang| thread's names to |CrashDataThresholds|.
429 static void ParseCommandLine(
430 const base::CommandLine
& command_line
,
431 uint32
* unresponsive_threshold
,
432 CrashOnHangThreadMap
* crash_on_hang_threads
);
434 // Parses the argument |crash_on_hang_thread_names| and creates
435 // |crash_on_hang_threads| map of |crash_on_hang| thread's names to
436 // |CrashDataThresholds|. If |crash_on_hang_thread_names| doesn't specify
437 // |live_threads_threshold|, then it uses |default_live_threads_threshold| as
438 // the value. If |crash_on_hang_thread_names| doesn't specify |crash_seconds|,
439 // then it uses |default_crash_seconds| as the value.
440 static void ParseCommandLineCrashOnHangThreads(
441 const std::string
& crash_on_hang_thread_names
,
442 uint32 default_live_threads_threshold
,
443 uint32 default_crash_seconds
,
444 CrashOnHangThreadMap
* crash_on_hang_threads
);
446 // This constructs the |ThreadWatcherList| singleton and starts watching
447 // browser threads by calling StartWatching() on each browser thread that is
448 // watched. It disarms StartupTimeBomb.
449 static void InitializeAndStartWatching(
450 uint32 unresponsive_threshold
,
451 const CrashOnHangThreadMap
& crash_on_hang_threads
);
453 // This method calls ThreadWatcher::StartWatching() to perform health check on
454 // the given |thread_id|.
455 static void StartWatching(
456 const content::BrowserThread::ID
& thread_id
,
457 const std::string
& thread_name
,
458 const base::TimeDelta
& sleep_time
,
459 const base::TimeDelta
& unresponsive_time
,
460 uint32 unresponsive_threshold
,
461 const CrashOnHangThreadMap
& crash_on_hang_threads
);
463 // Delete all thread watcher objects and remove them from global map. It also
464 // deletes |g_thread_watcher_list_|.
465 static void DeleteAll();
467 // The Find() method can be used to test to see if a given ThreadWatcher was
468 // already registered, or to retrieve a pointer to it from the global map.
469 static ThreadWatcher
* Find(const content::BrowserThread::ID
& thread_id
);
471 // Sets |g_stopped_| on the WatchDogThread. This is necessary to reflect the
472 // state between the delayed |StartWatchingAll| and the immediate
473 // |StopWatchingAll|.
474 static void SetStopped(bool stopped
);
476 // The singleton of this class and is used to keep track of information about
477 // threads that are being watched.
478 static ThreadWatcherList
* g_thread_watcher_list_
;
480 // StartWatchingAll() is delayed in relation to StopWatchingAll(), so if
481 // a Stop comes first, prevent further initialization.
482 static bool g_stopped_
;
484 // This is the wait time between ping messages.
485 static const int kSleepSeconds
;
487 // This is the wait time after ping message is sent, to check if we have
488 // received pong message or not.
489 static const int kUnresponsiveSeconds
;
491 // Default values for |unresponsive_threshold|.
492 static const int kUnresponsiveCount
;
494 // Default values for |live_threads_threshold|.
495 static const int kLiveThreadsThreshold
;
497 // Default value for the delay until |InitializeAndStartWatching| is called.
498 // Non-const for tests.
499 static int g_initialize_delay_seconds
;
501 // Map of all registered watched threads, from thread_id to ThreadWatcher.
502 RegistrationList registered_
;
504 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList
);
507 // This class ensures that the thread watching is actively taking place. Only
508 // one instance of this class exists.
509 class ThreadWatcherObserver
: public content::NotificationObserver
{
511 // Registers |g_thread_watcher_observer_| as the Notifications observer.
512 // |wakeup_interval| specifies how often to wake up thread watchers. This
513 // method is accessible on UI thread.
514 static void SetupNotifications(const base::TimeDelta
& wakeup_interval
);
516 // Removes all ints from |registrar_| and deletes
517 // |g_thread_watcher_observer_|. This method is accessible on UI thread.
518 static void RemoveNotifications();
521 // Constructor of |g_thread_watcher_observer_| singleton.
522 explicit ThreadWatcherObserver(const base::TimeDelta
& wakeup_interval
);
524 // Destructor of |g_thread_watcher_observer_| singleton.
525 ~ThreadWatcherObserver() override
;
527 // This ensures all thread watchers are active because there is some user
528 // activity. It will wake up all thread watchers every |wakeup_interval_|
529 // seconds. This is the implementation of content::NotificationObserver. When
530 // a matching notification is posted to the notification service, this method
532 void Observe(int type
,
533 const content::NotificationSource
& source
,
534 const content::NotificationDetails
& details
) override
;
536 // Called when a URL is opened from the Omnibox.
537 void OnURLOpenedFromOmnibox(OmniboxLog
* log
);
539 // Called when user activity is detected.
540 void OnUserActivityDetected();
542 // The singleton of this class.
543 static ThreadWatcherObserver
* g_thread_watcher_observer_
;
545 // The registrar that holds ints to be observed.
546 content::NotificationRegistrar registrar_
;
548 // This is the last time when woke all thread watchers up.
549 base::TimeTicks last_wakeup_time_
;
551 // It is the time interval between wake up calls to thread watchers.
552 const base::TimeDelta wakeup_interval_
;
554 // Subscription for receiving callbacks that a URL was opened from the
556 scoped_ptr
<base::CallbackList
<void(OmniboxLog
*)>::Subscription
>
557 omnibox_url_opened_subscription_
;
559 DISALLOW_COPY_AND_ASSIGN(ThreadWatcherObserver
);
562 // Class for WatchDogThread and in its Init method, we start watching UI, IO,
563 // DB, FILE, CACHED threads.
564 class WatchDogThread
: public base::Thread
{
569 // Destroys the thread and stops the thread.
570 ~WatchDogThread() override
;
572 // Callable on any thread. Returns whether you're currently on a
574 static bool CurrentlyOnWatchDogThread();
576 // These are the same methods in message_loop.h, but are guaranteed to either
577 // get posted to the MessageLoop if it's still alive, or be deleted otherwise.
578 // They return true iff the watchdog thread existed and the task was posted.
579 // Note that even if the task is posted, there's no guarantee that it will
580 // run, since the target thread may already have a Quit message in its queue.
581 static bool PostTask(const tracked_objects::Location
& from_here
,
582 const base::Closure
& task
);
583 static bool PostDelayedTask(const tracked_objects::Location
& from_here
,
584 const base::Closure
& task
,
585 base::TimeDelta delay
);
588 void Init() override
;
589 void CleanUp() override
;
592 static bool PostTaskHelper(
593 const tracked_objects::Location
& from_here
,
594 const base::Closure
& task
,
595 base::TimeDelta delay
);
597 DISALLOW_COPY_AND_ASSIGN(WatchDogThread
);
600 // This is a wrapper class for getting the crash dumps of the hangs during
602 class StartupTimeBomb
{
604 // This singleton is instantiated when the browser process is launched.
607 // Destructor disarm's startup_watchdog_ (if it is arm'ed) so that alarm
611 // Constructs |startup_watchdog_| which spawns a thread and starts timer.
612 // |duration| specifies how long |startup_watchdog_| will wait before it
614 void Arm(const base::TimeDelta
& duration
);
616 // Disarms |startup_watchdog_| thread and then deletes it which stops the
620 // Disarms |g_startup_timebomb_|.
621 static void DisarmStartupTimeBomb();
624 // Deletes |startup_watchdog_| if it is joinable. If |startup_watchdog_| is
625 // not joinable, then it will post a delayed task to try again.
626 void DeleteStartupWatchdog();
628 // The singleton of this class.
629 static StartupTimeBomb
* g_startup_timebomb_
;
631 // Watches for hangs during startup until it is disarm'ed.
632 base::Watchdog
* startup_watchdog_
;
634 // The |thread_id_| on which this object is constructed.
635 const base::PlatformThreadId thread_id_
;
637 DISALLOW_COPY_AND_ASSIGN(StartupTimeBomb
);
640 // This is a wrapper class for detecting hangs during shutdown.
641 class ShutdownWatcherHelper
{
643 // Create an empty holder for |shutdown_watchdog_|.
644 ShutdownWatcherHelper();
646 // Destructor disarm's shutdown_watchdog_ so that alarm doesn't go off.
647 ~ShutdownWatcherHelper();
649 // Constructs ShutdownWatchDogThread which spawns a thread and starts timer.
650 // |duration| specifies how long it will wait before it calls alarm.
651 void Arm(const base::TimeDelta
& duration
);
654 // shutdown_watchdog_ watches for hangs during shutdown.
655 base::Watchdog
* shutdown_watchdog_
;
657 // The |thread_id_| on which this object is constructed.
658 const base::PlatformThreadId thread_id_
;
660 DISALLOW_COPY_AND_ASSIGN(ShutdownWatcherHelper
);
663 #endif // CHROME_BROWSER_METRICS_THREAD_WATCHER_H_