Index: chrome/browser/metrics/thread_watcher.cc |
=================================================================== |
--- chrome/browser/metrics/thread_watcher.cc (revision 181723) |
+++ chrome/browser/metrics/thread_watcher.cc (working copy) |
@@ -11,6 +11,7 @@ |
#include "base/debug/alias.h" |
#include "base/lazy_instance.h" |
#include "base/string_split.h" |
+#include "base/stringprintf.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_tokenizer.h" |
#include "base/threading/thread_restrictions.h" |
@@ -408,6 +409,18 @@ |
// static |
const int ThreadWatcherList::kLiveThreadsThreshold = 3; |
+ThreadWatcherList::CrashDataThresholds::CrashDataThresholds( |
+ uint32 live_threads_threshold, |
+ uint32 unresponsive_threshold) |
+ : live_threads_threshold(live_threads_threshold), |
+ unresponsive_threshold(unresponsive_threshold) { |
+} |
+ |
+ThreadWatcherList::CrashDataThresholds::CrashDataThresholds() |
+ : live_threads_threshold(kLiveThreadsThreshold), |
+ unresponsive_threshold(kUnresponsiveCount) { |
+} |
+ |
// static |
void ThreadWatcherList::StartWatchingAll(const CommandLine& command_line) { |
uint32 unresponsive_threshold; |
@@ -498,7 +511,7 @@ |
const CommandLine& command_line, |
uint32* unresponsive_threshold, |
CrashOnHangThreadMap* crash_on_hang_threads) { |
- // Determine |unresponsive_threshold| based on switches::kCrashOnHangSeconds. |
+ // Initialize |unresponsive_threshold| to a default value. |
*unresponsive_threshold = kUnresponsiveCount; |
// Increase the unresponsive_threshold on the Stable and Beta channels to |
@@ -518,48 +531,28 @@ |
*unresponsive_threshold *= 2; |
#endif |
- std::string crash_on_hang_seconds = |
- command_line.GetSwitchValueASCII(switches::kCrashOnHangSeconds); |
- if (!crash_on_hang_seconds.empty()) { |
- int crash_seconds = atoi(crash_on_hang_seconds.c_str()); |
- if (crash_seconds > 0) { |
- *unresponsive_threshold = static_cast<uint32>( |
- ceil(static_cast<float>(crash_seconds) / kUnresponsiveSeconds)); |
- } |
- } |
- |
+ uint32 crash_seconds = *unresponsive_threshold * kUnresponsiveSeconds; |
std::string crash_on_hang_thread_names; |
- |
- // Default to crashing the browser if UI or IO threads are not responsive |
- // except in stable channel. |
- if (channel == chrome::VersionInfo::CHANNEL_STABLE) |
- crash_on_hang_thread_names = ""; |
- else |
- crash_on_hang_thread_names = "UI:3,IO:9"; |
- |
bool has_command_line_overwrite = false; |
if (command_line.HasSwitch(switches::kCrashOnHangThreads)) { |
crash_on_hang_thread_names = |
command_line.GetSwitchValueASCII(switches::kCrashOnHangThreads); |
has_command_line_overwrite = true; |
+ } else if (channel != chrome::VersionInfo::CHANNEL_STABLE) { |
+ // Default to crashing the browser if UI or IO or FILE threads are not |
+ // responsive except in stable channel. |
+ crash_on_hang_thread_names = base::StringPrintf( |
+ "UI:%d:%d,IO:%d:%d,FILE:%d:%d", |
+ kLiveThreadsThreshold, crash_seconds, |
+ kLiveThreadsThreshold, crash_seconds, |
+ kLiveThreadsThreshold, crash_seconds * 5); |
} |
- base::StringTokenizer tokens(crash_on_hang_thread_names, ","); |
- std::vector<std::string> values; |
- while (tokens.GetNext()) { |
- const std::string& token = tokens.token(); |
- base::SplitString(token, ':', &values); |
- if (values.size() != 2) |
- continue; |
- std::string thread_name = values[0]; |
- uint32 live_threads_threshold; |
- if (!base::StringToUint(values[1], &live_threads_threshold)) |
- continue; |
- CrashOnHangThreadMap::iterator it = |
- crash_on_hang_threads->find(thread_name); |
- if (crash_on_hang_threads->end() == it) |
- (*crash_on_hang_threads)[thread_name] = live_threads_threshold; |
- } |
+ ParseCommandLineCrashOnHangThreads(crash_on_hang_thread_names, |
+ kLiveThreadsThreshold, |
+ crash_seconds, |
+ crash_on_hang_threads); |
+ |
if (channel != chrome::VersionInfo::CHANNEL_CANARY || |
has_command_line_overwrite) { |
return; |
@@ -576,11 +569,46 @@ |
"ThreadWatcher", 100, "default_hung_threads", |
2013, 10, 30, NULL)); |
int io_hung_thread_group = field_trial->AppendGroup("io_hung_thread", 10); |
- if (field_trial->group() == io_hung_thread_group) |
- it->second = INT_MAX; // Crash anytime IO thread hangs. |
+ if (field_trial->group() == io_hung_thread_group) { |
+ // Crash anytime IO thread hangs. |
+ it->second.live_threads_threshold = INT_MAX; |
+ } |
} |
// static |
+void ThreadWatcherList::ParseCommandLineCrashOnHangThreads( |
+ const std::string& crash_on_hang_thread_names, |
+ uint32 default_live_threads_threshold, |
+ uint32 default_crash_seconds, |
+ CrashOnHangThreadMap* crash_on_hang_threads) { |
+ base::StringTokenizer tokens(crash_on_hang_thread_names, ","); |
+ std::vector<std::string> values; |
+ while (tokens.GetNext()) { |
+ const std::string& token = tokens.token(); |
+ base::SplitString(token, ':', &values); |
+ std::string thread_name = values[0]; |
+ |
+ uint32 live_threads_threshold = default_live_threads_threshold; |
+ uint32 crash_seconds = default_crash_seconds; |
+ if (values.size() >= 2 && |
+ (!base::StringToUint(values[1], &live_threads_threshold))) { |
+ continue; |
+ } |
+ if (values.size() >= 3 && |
+ (!base::StringToUint(values[2], &crash_seconds))) { |
+ continue; |
+ } |
+ uint32 unresponsive_threshold = static_cast<uint32>( |
+ ceil(static_cast<float>(crash_seconds) / kUnresponsiveSeconds)); |
+ |
+ CrashDataThresholds crash_data(live_threads_threshold, |
+ unresponsive_threshold); |
+ // Use the last specifier. |
+ (*crash_on_hang_threads)[thread_name] = crash_data; |
+ } |
+} |
+ |
+// static |
void ThreadWatcherList::InitializeAndStartWatching( |
uint32 unresponsive_threshold, |
const CrashOnHangThreadMap& crash_on_hang_threads) { |
@@ -630,7 +658,8 @@ |
uint32 live_threads_threshold = 0; |
if (it != crash_on_hang_threads.end()) { |
crash_on_hang = true; |
- live_threads_threshold = it->second; |
+ live_threads_threshold = it->second.live_threads_threshold; |
+ unresponsive_threshold = it->second.unresponsive_threshold; |
} |
ThreadWatcher::StartWatching( |