| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "chrome/browser/metrics/thread_watcher.h" | 5 #include "chrome/browser/metrics/thread_watcher.h" |
| 6 | 6 |
| 7 #include <math.h> // ceil | 7 #include <math.h> // ceil |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/debug/dump_without_crashing.h" | 11 #include "base/debug/dump_without_crashing.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/location.h" |
| 13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
| 15 #include "base/strings/string_tokenizer.h" | 16 #include "base/strings/string_tokenizer.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/thread_task_runner_handle.h" |
| 17 #include "base/threading/thread_restrictions.h" | 19 #include "base/threading/thread_restrictions.h" |
| 18 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 19 #include "chrome/browser/chrome_notification_types.h" | 21 #include "chrome/browser/chrome_notification_types.h" |
| 20 #include "chrome/browser/metrics/thread_watcher_report_hang.h" | 22 #include "chrome/browser/metrics/thread_watcher_report_hang.h" |
| 21 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/chrome_version_info.h" | 24 #include "chrome/common/chrome_version_info.h" |
| 23 #include "chrome/common/logging_chrome.h" | 25 #include "chrome/common/logging_chrome.h" |
| 24 #include "content/public/browser/notification_service.h" | 26 #include "content/public/browser/notification_service.h" |
| 25 | 27 |
| 26 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 return; | 85 return; |
| 84 watcher->ActivateThreadWatching(); | 86 watcher->ActivateThreadWatching(); |
| 85 } | 87 } |
| 86 | 88 |
| 87 void ThreadWatcher::ActivateThreadWatching() { | 89 void ThreadWatcher::ActivateThreadWatching() { |
| 88 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 90 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 89 if (active_) return; | 91 if (active_) return; |
| 90 active_ = true; | 92 active_ = true; |
| 91 ping_count_ = unresponsive_threshold_; | 93 ping_count_ = unresponsive_threshold_; |
| 92 ResetHangCounters(); | 94 ResetHangCounters(); |
| 93 base::MessageLoop::current()->PostTask( | 95 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 94 FROM_HERE, | 96 FROM_HERE, base::Bind(&ThreadWatcher::PostPingMessage, |
| 95 base::Bind(&ThreadWatcher::PostPingMessage, | 97 weak_ptr_factory_.GetWeakPtr())); |
| 96 weak_ptr_factory_.GetWeakPtr())); | |
| 97 } | 98 } |
| 98 | 99 |
| 99 void ThreadWatcher::DeActivateThreadWatching() { | 100 void ThreadWatcher::DeActivateThreadWatching() { |
| 100 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 101 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 101 active_ = false; | 102 active_ = false; |
| 102 ping_count_ = 0; | 103 ping_count_ = 0; |
| 103 weak_ptr_factory_.InvalidateWeakPtrs(); | 104 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 104 } | 105 } |
| 105 | 106 |
| 106 void ThreadWatcher::WakeUp() { | 107 void ThreadWatcher::WakeUp() { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 176 |
| 176 // Increment sequence number for the next ping message to indicate watched | 177 // Increment sequence number for the next ping message to indicate watched |
| 177 // thread is responsive. | 178 // thread is responsive. |
| 178 ++ping_sequence_number_; | 179 ++ping_sequence_number_; |
| 179 | 180 |
| 180 // If we have stopped watching or if the user is idle, then stop sending | 181 // If we have stopped watching or if the user is idle, then stop sending |
| 181 // ping messages. | 182 // ping messages. |
| 182 if (!active_ || --ping_count_ <= 0) | 183 if (!active_ || --ping_count_ <= 0) |
| 183 return; | 184 return; |
| 184 | 185 |
| 185 base::MessageLoop::current()->PostDelayedTask( | 186 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 186 FROM_HERE, | 187 FROM_HERE, base::Bind(&ThreadWatcher::PostPingMessage, |
| 187 base::Bind(&ThreadWatcher::PostPingMessage, | 188 weak_ptr_factory_.GetWeakPtr()), |
| 188 weak_ptr_factory_.GetWeakPtr()), | |
| 189 sleep_time_); | 189 sleep_time_); |
| 190 } | 190 } |
| 191 | 191 |
| 192 void ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { | 192 void ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { |
| 193 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 193 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 194 // If we have stopped watching then consider thread as responding. | 194 // If we have stopped watching then consider thread as responding. |
| 195 if (!active_) { | 195 if (!active_) { |
| 196 responsive_ = true; | 196 responsive_ = true; |
| 197 return; | 197 return; |
| 198 } | 198 } |
| 199 // If the latest ping_sequence_number_ is not same as the ping_sequence_number | 199 // If the latest ping_sequence_number_ is not same as the ping_sequence_number |
| 200 // that is passed in, then we can assume OnPongMessage was called. | 200 // that is passed in, then we can assume OnPongMessage was called. |
| 201 // OnPongMessage increments ping_sequence_number_. | 201 // OnPongMessage increments ping_sequence_number_. |
| 202 if (ping_sequence_number_ != ping_sequence_number) { | 202 if (ping_sequence_number_ != ping_sequence_number) { |
| 203 // Reset unresponsive_count_ to zero because we got a response from the | 203 // Reset unresponsive_count_ to zero because we got a response from the |
| 204 // watched thread. | 204 // watched thread. |
| 205 ResetHangCounters(); | 205 ResetHangCounters(); |
| 206 | 206 |
| 207 responsive_ = true; | 207 responsive_ = true; |
| 208 return; | 208 return; |
| 209 } | 209 } |
| 210 // Record that we got no response from watched thread. | 210 // Record that we got no response from watched thread. |
| 211 GotNoResponse(); | 211 GotNoResponse(); |
| 212 | 212 |
| 213 // Post a task to check the responsiveness of watched thread. | 213 // Post a task to check the responsiveness of watched thread. |
| 214 base::MessageLoop::current()->PostDelayedTask( | 214 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 215 FROM_HERE, | 215 FROM_HERE, |
| 216 base::Bind(&ThreadWatcher::OnCheckResponsiveness, | 216 base::Bind(&ThreadWatcher::OnCheckResponsiveness, |
| 217 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), | 217 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), |
| 218 unresponsive_time_); | 218 unresponsive_time_); |
| 219 responsive_ = false; | 219 responsive_ = false; |
| 220 } | 220 } |
| 221 | 221 |
| 222 void ThreadWatcher::Initialize() { | 222 void ThreadWatcher::Initialize() { |
| 223 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 223 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 224 ThreadWatcherList::Register(this); | 224 ThreadWatcherList::Register(this); |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 bool WatchDogThread::PostTaskHelper( | 756 bool WatchDogThread::PostTaskHelper( |
| 757 const tracked_objects::Location& from_here, | 757 const tracked_objects::Location& from_here, |
| 758 const base::Closure& task, | 758 const base::Closure& task, |
| 759 base::TimeDelta delay) { | 759 base::TimeDelta delay) { |
| 760 { | 760 { |
| 761 base::AutoLock lock(g_watchdog_lock.Get()); | 761 base::AutoLock lock(g_watchdog_lock.Get()); |
| 762 | 762 |
| 763 base::MessageLoop* message_loop = g_watchdog_thread ? | 763 base::MessageLoop* message_loop = g_watchdog_thread ? |
| 764 g_watchdog_thread->message_loop() : NULL; | 764 g_watchdog_thread->message_loop() : NULL; |
| 765 if (message_loop) { | 765 if (message_loop) { |
| 766 message_loop->PostDelayedTask(from_here, task, delay); | 766 message_loop->task_runner()->PostDelayedTask(from_here, task, delay); |
| 767 return true; | 767 return true; |
| 768 } | 768 } |
| 769 } | 769 } |
| 770 | 770 |
| 771 return false; | 771 return false; |
| 772 } | 772 } |
| 773 | 773 |
| 774 void WatchDogThread::Init() { | 774 void WatchDogThread::Init() { |
| 775 // This thread shouldn't be allowed to perform any blocking disk I/O. | 775 // This thread shouldn't be allowed to perform any blocking disk I/O. |
| 776 base::ThreadRestrictions::SetIOAllowed(false); | 776 base::ThreadRestrictions::SetIOAllowed(false); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 void StartupTimeBomb::DeleteStartupWatchdog() { | 877 void StartupTimeBomb::DeleteStartupWatchdog() { |
| 878 DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId()); | 878 DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId()); |
| 879 if (startup_watchdog_->IsJoinable()) { | 879 if (startup_watchdog_->IsJoinable()) { |
| 880 // Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns | 880 // Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns |
| 881 // very fast. | 881 // very fast. |
| 882 base::ThreadRestrictions::SetIOAllowed(true); | 882 base::ThreadRestrictions::SetIOAllowed(true); |
| 883 delete startup_watchdog_; | 883 delete startup_watchdog_; |
| 884 startup_watchdog_ = NULL; | 884 startup_watchdog_ = NULL; |
| 885 return; | 885 return; |
| 886 } | 886 } |
| 887 base::MessageLoop::current()->PostDelayedTask( | 887 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 888 FROM_HERE, | 888 FROM_HERE, base::Bind(&StartupTimeBomb::DeleteStartupWatchdog, |
| 889 base::Bind(&StartupTimeBomb::DeleteStartupWatchdog, | 889 base::Unretained(this)), |
| 890 base::Unretained(this)), | |
| 891 base::TimeDelta::FromSeconds(10)); | 890 base::TimeDelta::FromSeconds(10)); |
| 892 } | 891 } |
| 893 | 892 |
| 894 // static | 893 // static |
| 895 void StartupTimeBomb::DisarmStartupTimeBomb() { | 894 void StartupTimeBomb::DisarmStartupTimeBomb() { |
| 896 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 895 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 897 if (g_startup_timebomb_) | 896 if (g_startup_timebomb_) |
| 898 g_startup_timebomb_->Disarm(); | 897 g_startup_timebomb_->Disarm(); |
| 899 } | 898 } |
| 900 | 899 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 931 | 930 |
| 932 #if defined(OS_WIN) | 931 #if defined(OS_WIN) |
| 933 // On Windows XP, give twice the time for shutdown. | 932 // On Windows XP, give twice the time for shutdown. |
| 934 if (base::win::GetVersion() <= base::win::VERSION_XP) | 933 if (base::win::GetVersion() <= base::win::VERSION_XP) |
| 935 actual_duration *= 2; | 934 actual_duration *= 2; |
| 936 #endif | 935 #endif |
| 937 | 936 |
| 938 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); | 937 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); |
| 939 shutdown_watchdog_->Arm(); | 938 shutdown_watchdog_->Arm(); |
| 940 } | 939 } |
| OLD | NEW |