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

Unified Diff: chrome/browser/metrics/thread_watcher.h

Issue 7134007: Added command line switches "crash-on-hang-threads" and "crash-on-hang-seconds" (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/browser_main.cc ('k') | chrome/browser/metrics/thread_watcher.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/metrics/thread_watcher.h
===================================================================
--- chrome/browser/metrics/thread_watcher.h (revision 89361)
+++ chrome/browser/metrics/thread_watcher.h (working copy)
@@ -18,24 +18,37 @@
//
// Example Usage:
//
-// The following is an example for watching responsiveness of IO thread.
-// sleep_time specifies how often ping messages have to be sent to IO thread.
-// unresponsive_time is the wait time after ping message is sent, to check if
-// we have received pong message or not.
+// The following is an example for watching responsiveness of watched (IO)
+// thread. |sleep_time| specifies how often ping messages have to be sent to
+// watched (IO) thread. |unresponsive_time| is the wait time after ping
+// message is sent, to check if we have received pong message or not.
+// |unresponsive_threshold| specifies the number of unanswered ping messages
+// after which watched (IO) thread is considered as not responsive.
+// |crash_on_hang| specifies if we want to crash the browser when the watched
+// (IO) thread has become sufficiently unresponsive, while other threads are
+// sufficiently responsive. |live_threads_threshold| specifies the number of
+// browser threads that are to be responsive when we want to crash the browser
+// because of hung watched (IO) thread.
//
// base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(5);
// base::TimeDelta unresponsive_time = base::TimeDelta::FromSeconds(10);
-// ThreadWatcher::StartWatching(BrowserThread::IO, "IO", sleep_time,
-// unresponsive_time);
+// uint32 unresponsive_threshold = ThreadWatcherList::kUnresponsiveCount;
+// bool crash_on_hang = false;
+// uint32 live_threads_threshold = ThreadWatcherList::kLiveThreadsThreshold;
+// ThreadWatcher::StartWatching(
+// BrowserThread::IO, "IO", sleep_time, unresponsive_time,
+// unresponsive_threshold, crash_on_hang, live_threads_threshold);
#ifndef CHROME_BROWSER_METRICS_THREAD_WATCHER_H_
#define CHROME_BROWSER_METRICS_THREAD_WATCHER_H_
#include <map>
+#include <set>
#include <string>
#include <vector>
#include "base/basictypes.h"
+#include "base/command_line.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -51,23 +64,33 @@
class CustomThreadWatcher;
class ThreadWatcherList;
+class ThreadWatcherObserver;
// This class performs health check on threads that would like to be watched.
class ThreadWatcher {
public:
- // This method starts performing health check on the given thread_id. It will
- // create ThreadWatcher object for the given thread_id, thread_name,
- // sleep_time and unresponsive_time. sleep_time_ is the wait time between ping
- // messages. unresponsive_time_ is the wait time after ping message is sent,
- // to check if we have received pong message or not. It will register that
- // ThreadWatcher object and activate the thread watching of the given
- // thread_id.
+ // This method starts performing health check on the given |thread_id|. It
+ // will create ThreadWatcher object for the given |thread_id|, |thread_name|.
+ // |sleep_time| is the wait time between ping messages. |unresponsive_time| is
+ // the wait time after ping message is sent, to check if we have received pong
+ // message or not. |unresponsive_threshold| is used to determine if the thread
+ // is responsive or not. The watched thread is considered unresponsive if it
+ // hasn't responded with a pong message for |unresponsive_threshold| number of
+ // ping messages. |crash_on_hang| specifies if browser should be crashed when
+ // the watched thread is unresponsive. |live_threads_threshold| specifies the
+ // number of browser threads that are to be responsive when we want to crash
+ // the browser and watched thread has become sufficiently unresponsive. It
+ // will register that ThreadWatcher object and activate the thread watching of
+ // the given thread_id.
static void StartWatching(const BrowserThread::ID& thread_id,
const std::string& thread_name,
const base::TimeDelta& sleep_time,
- const base::TimeDelta& unresponsive_time);
+ const base::TimeDelta& unresponsive_time,
+ uint32 unresponsive_threshold,
+ bool crash_on_hang,
+ uint32 live_threads_threshold);
- // Return the thread_id of the thread being watched.
+ // Return the |thread_id_| of the thread being watched.
BrowserThread::ID thread_id() const { return thread_id_; }
// Return the name of the thread being watched.
@@ -82,20 +105,23 @@
// Returns true if we are montioring the thread.
bool active() const { return active_; }
- // Returns ping_time_ (used by unit tests).
+ // Returns |ping_time_| (used by unit tests).
base::TimeTicks ping_time() const { return ping_time_; }
- // Returns ping_sequence_number_ (used by unit tests).
+ // Returns |ping_sequence_number_| (used by unit tests).
uint64 ping_sequence_number() const { return ping_sequence_number_; }
protected:
- // Construct a ThreadWatcher for the given thread_id. sleep_time_ is the
- // wait time between ping messages. unresponsive_time_ is the wait time after
+ // Construct a ThreadWatcher for the given |thread_id|. |sleep_time| is the
+ // wait time between ping messages. |unresponsive_time| is the wait time after
// ping message is sent, to check if we have received pong message or not.
ThreadWatcher(const BrowserThread::ID& thread_id,
const std::string& thread_name,
const base::TimeDelta& sleep_time,
- const base::TimeDelta& unresponsive_time);
+ const base::TimeDelta& unresponsive_time,
+ uint32 unresponsive_threshold,
+ bool crash_on_hang,
+ uint32 live_threads_threshold);
virtual ~ThreadWatcher();
// This method activates the thread watching which starts ping/pong messaging.
@@ -105,29 +131,29 @@
virtual void DeActivateThreadWatching();
// This will ensure that the watching is actively taking place, and awaken
- // (i.e., post a PostPingMessage) if the watcher has stopped pinging due to
- // lack of user activity. It will also reset ping_count_ to kPingCount.
+ // (i.e., post a PostPingMessage()) if the watcher has stopped pinging due to
+ // lack of user activity. It will also reset |ping_count_| to |kPingCount|.
virtual void WakeUp();
// This method records when ping message was sent and it will Post a task
- // (OnPingMessage) to the watched thread that does nothing but respond with
- // OnPongMessage. It also posts a task (OnCheckResponsiveness) to check
+ // (OnPingMessage()) to the watched thread that does nothing but respond with
+ // OnPongMessage(). It also posts a task (OnCheckResponsiveness()) to check
// responsiveness of monitored thread that would be called after waiting
- // unresponsive_time_.
+ // |unresponsive_time_|.
// This method is accessible on WatchDogThread.
virtual void PostPingMessage();
// This method handles a Pong Message from watched thread. It will track the
// response time (pong time minus ping time) via histograms. It posts a
- // PostPingMessage task that would be called after waiting sleep_time_. It
- // increments ping_sequence_number_ by 1.
+ // PostPingMessage() task that would be called after waiting |sleep_time_|. It
+ // increments |ping_sequence_number_| by 1.
// This method is accessible on WatchDogThread.
virtual void OnPongMessage(uint64 ping_sequence_number);
// This method will determine if the watched thread is responsive or not. If
- // the latest ping_sequence_number_ is not same as the ping_sequence_number
- // that is passed in, then we can assume that watched thread has responded
- // with a pong message.
+ // the latest |ping_sequence_number_| is not same as the
+ // |ping_sequence_number| that is passed in, then we can assume that watched
+ // thread has responded with a pong message.
// This method is accessible on WatchDogThread.
virtual bool OnCheckResponsiveness(uint64 ping_sequence_number);
@@ -150,33 +176,31 @@
static void OnPingMessage(const BrowserThread::ID& thread_id,
Task* callback_task);
- // This method resets unresponsive_count_ to zero because watched thread is
+ // This method resets |unresponsive_count_| to zero because watched thread is
// responding to the ping message with a pong message.
void ResetHangCounters();
// This method records watched thread is not responding to the ping message.
- // It increments unresponsive_count_ by 1.
+ // It increments |unresponsive_count_| by 1.
void GotNoResponse();
+ // This method returns true if the watched thread has not responded with a
+ // pong message for |unresponsive_threshold_| number of ping messages.
+ bool IsVeryUnresponsive();
+
// This is the number of ping messages to be sent when the user is idle.
// ping_count_ will be initialized to kPingCount whenever user becomes active.
static const int kPingCount;
- // This value is used to determine if the watched thread is responsive or not.
- // If unresponsive_count_ is less than kUnresponsiveCount then watched thread
- // is considered as responsive (in responsive_count_histogram_) otherwise it
- // is considered as unresponsive (in unresponsive_count_histogram_).
- static const int kUnresponsiveCount;
-
- // The thread_id of the thread being watched. Only one instance can exist for
- // the given thread_id of the thread being watched.
+ // The |thread_id_| of the thread being watched. Only one instance can exist
+ // for the given |thread_id_| of the thread being watched.
const BrowserThread::ID thread_id_;
// The name of the thread being watched.
const std::string thread_name_;
- // It is the sleep time between between the receipt of a pong message back,
- // and the sending of another ping message.
+ // It is the sleep time between the receipt of a pong message back, and the
+ // sending of another ping message.
const base::TimeDelta sleep_time_;
// It is the duration from sending a ping message, until we check status to be
@@ -207,29 +231,44 @@
base::Histogram* response_time_histogram_;
// Histogram that keeps track of unresponsive time since the last pong message
- // when we got no response (GotNoResponse) from the watched thread.
+ // when we got no response (GotNoResponse()) from the watched thread.
base::Histogram* unresponsive_time_histogram_;
// Histogram that keeps track of how many threads are responding when we got
- // no response (GotNoResponse) from the watched thread.
+ // no response (GotNoResponse()) from the watched thread.
base::Histogram* responsive_count_histogram_;
// Histogram that keeps track of how many threads are not responding when we
- // got no response (GotNoResponse) from the watched thread. Count includes the
- // thread that got no response.
+ // got no response (GotNoResponse()) from the watched thread. Count includes
+ // the thread that got no response.
base::Histogram* unresponsive_count_histogram_;
// This counter tracks the unresponsiveness of watched thread. If this value
// is zero then watched thread has responded with a pong message. This is
- // incremented by 1 when we got no response (GotNoResponse) from the watched
+ // incremented by 1 when we got no response (GotNoResponse()) from the watched
// thread.
- int unresponsive_count_;
+ uint32 unresponsive_count_;
// This is set to true when we would have crashed the browser because the
// watched thread hasn't responded atleast 6 times. It is reset to false when
// watched thread responds with a pong message.
bool hung_processing_complete_;
+ // This is used to determine if the watched thread is responsive or not. If
+ // watched thread's |unresponsive_count_| is greater than or equal to
+ // |unresponsive_threshold_| then we would consider it as unresponsive.
+ uint32 unresponsive_threshold_;
+
+ // This is set to true if we want to crash the browser when the watched thread
+ // has become sufficiently unresponsive, while other threads are sufficiently
+ // responsive.
+ bool crash_on_hang_;
+
+ // This specifies the number of browser threads that are to be responsive when
+ // we want to crash the browser because watched thread has become sufficiently
+ // unresponsive.
+ uint32 live_threads_threshold_;
+
// We use this factory to create callback tasks for ThreadWatcher object. We
// use this during ping-pong messaging between WatchDog thread and watched
// thread.
@@ -242,26 +281,15 @@
// if it has been registered, which includes determing the histogram name. This
// class provides utility functions to start and stop watching all browser
// threads. Only one instance of this class exists.
-class ThreadWatcherList : public NotificationObserver {
+class ThreadWatcherList {
public:
// A map from BrowserThread to the actual instances.
typedef std::map<BrowserThread::ID, ThreadWatcher*> RegistrationList;
- // This singleton holds the global list of registered ThreadWatchers.
- ThreadWatcherList();
- // Destructor deletes all registered ThreadWatcher instances.
- virtual ~ThreadWatcherList();
-
- // Register() stores a pointer to the given ThreadWatcher in a global map.
- static void Register(ThreadWatcher* watcher);
-
- // This method returns true if the ThreadWatcher object is registerd.
- static bool IsRegistered(const BrowserThread::ID thread_id);
-
// This method posts a task on WatchDogThread to start watching all browser
// threads.
// This method is accessible on UI thread.
- static void StartWatchingAll();
+ static void StartWatchingAll(const CommandLine& command_line);
// This method posts a task on WatchDogThread to RevokeAll tasks and to
// deactive thread watching of other threads and tell NotificationService to
@@ -269,46 +297,74 @@
// This method is accessible on UI thread.
static void StopWatchingAll();
- // RemoveAll NotificationTypes that are being observed.
- // This method is accessible on UI thread.
- static void RemoveNotifications();
+ // Register() stores a pointer to the given ThreadWatcher in a global map.
+ static void Register(ThreadWatcher* watcher);
- // This method returns number of watched threads that have responded and
- // threads that have not responded with a pong message.
- static void GetStatusOfThreads(int* no_of_responding_threads,
- int* no_of_unresponding_threads);
+ // This method returns true if the ThreadWatcher object is registerd.
+ static bool IsRegistered(const BrowserThread::ID thread_id);
+ // This method returns number of responsive and unresponsive watched threads.
+ static void GetStatusOfThreads(uint32* responding_thread_count,
+ uint32* unresponding_thread_count);
+
+ // This will ensure that the watching is actively taking place, and awaken
+ // all thread watchers that are registered.
+ static void WakeUpAll();
+
private:
// Allow tests to access our innards for testing purposes.
- FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, Registration);
+ friend class CustomThreadWatcher;
+ friend class ThreadWatcherTest;
+ FRIEND_TEST_ALL_PREFIXES(ThreadWatcherTest, CommandLineArgs);
- // Delete all thread watcher objects and remove them from global map.
- // This method is accessible on WatchDogThread.
- void DeleteAll();
+ // This singleton holds the global list of registered ThreadWatchers.
+ ThreadWatcherList();
- // This will ensure that the watching is actively taking place. It will wakeup
- // all thread watchers every 2 seconds. This is the implementation of
- // NotificationObserver. When a matching notification is posted to the
- // notification service, this method is called.
- // This method is accessible on UI thread.
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
+ // Destructor deletes all registered ThreadWatcher instances.
+ virtual ~ThreadWatcherList();
- // This will ensure that the watching is actively taking place, and awaken
- // all thread watchers that are registered.
- // This method is accessible on WatchDogThread.
- virtual void WakeUpAll();
+ // Parses the command line to get |unresponsive_threshold| from
+ // switches::kCrashOnHangSeconds, |crash_on_hang_thread_names| from
+ // switches::kCrashOnHangThreads and |live_threads_threshold| from
+ // switches::kCrashOnLive. |crash_on_hang_thread_names| is the set of watched
+ // thread's names that are to be crashed if they are not responding.
+ static void ParseCommandLine(
+ const CommandLine& command_line,
+ uint32* unresponsive_threshold,
+ std::set<std::string>* crash_on_hang_thread_names,
+ uint32* live_threads_threshold);
+ // This constructs the |ThreadWatcherList| singleton and starts watching
+ // browser threads by calling StartWatching() on each browser thread that is
+ // watched.
+ static void InitializeAndStartWatching(
+ uint32 unresponsive_threshold,
+ const std::set<std::string>& crash_on_hang_thread_names,
+ uint32 live_threads_threshold);
+
+ // This method calls ThreadWatcher::StartWatching() to perform health check on
+ // the given |thread_id|.
+ static void StartWatching(
+ const BrowserThread::ID& thread_id,
+ const std::string& thread_name,
+ const base::TimeDelta& sleep_time,
+ const base::TimeDelta& unresponsive_time,
+ uint32 unresponsive_threshold,
+ const std::set<std::string>& crash_on_hang_thread_names,
+ uint32 live_threads_threshold);
+
+ // Delete all thread watcher objects and remove them from global map. It also
+ // deletes |g_thread_watcher_list_|.
+ static void DeleteAll();
+
// The Find() method can be used to test to see if a given ThreadWatcher was
// already registered, or to retrieve a pointer to it from the global map.
static ThreadWatcher* Find(const BrowserThread::ID& thread_id);
- // Helper function should be called only while holding lock_.
- ThreadWatcher* PreLockedFind(const BrowserThread::ID& thread_id);
+ // The singleton of this class and is used to keep track of information about
+ // threads that are being watched.
+ static ThreadWatcherList* g_thread_watcher_list_;
- static ThreadWatcherList* global_; // The singleton of this class.
-
// This is the wait time between ping messages.
static const int kSleepSeconds;
@@ -316,19 +372,60 @@
// received pong message or not.
static const int kUnresponsiveSeconds;
- // Lock for access to registered_.
- base::Lock lock_;
+ // Default values for |unresponsive_threshold|.
+ static const int kUnresponsiveCount;
+ // Default values for |live_threads_threshold|.
+ static const int kLiveThreadsThreshold;
+
// Map of all registered watched threads, from thread_id to ThreadWatcher.
RegistrationList registered_;
+ DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList);
+};
+
+// This class ensures that the thread watching is actively taking place. Only
+// one instance of this class exists.
+class ThreadWatcherObserver : public NotificationObserver {
+ public:
+ // Registers |g_thread_watcher_observer_| as the Notifications observer.
+ // |wakeup_interval| specifies how often to wake up thread watchers. This
+ // method is accessible on UI thread.
+ static void SetupNotifications(const base::TimeDelta& wakeup_interval);
+
+ // Removes all NotificationTypes from |registrar_| and deletes
+ // |g_thread_watcher_observer_|. This method is accessible on UI thread.
+ static void RemoveNotifications();
+
+ private:
+ // Constructor of |g_thread_watcher_observer_| singleton.
+ explicit ThreadWatcherObserver(const base::TimeDelta& wakeup_interval);
+
+ // Destructor of |g_thread_watcher_observer_| singleton.
+ virtual ~ThreadWatcherObserver();
+
+ // This ensures all thread watchers are active because there is some user
+ // activity. It will wake up all thread watchers every |wakeup_interval_|
+ // seconds. This is the implementation of NotificationObserver. When a
+ // matching notification is posted to the notification service, this method is
+ // called.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // The singleton of this class.
+ static ThreadWatcherObserver* g_thread_watcher_observer_;
+
// The registrar that holds NotificationTypes to be observed.
NotificationRegistrar registrar_;
// This is the last time when woke all thread watchers up.
base::TimeTicks last_wakeup_time_;
- DISALLOW_COPY_AND_ASSIGN(ThreadWatcherList);
+ // It is the time interval between wake up calls to thread watchers.
+ const base::TimeDelta wakeup_interval_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadWatcherObserver);
};
// Class for WatchDogThread and in its Init method, we start watching UI, IO,
« no previous file with comments | « chrome/browser/browser_main.cc ('k') | chrome/browser/metrics/thread_watcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698