| 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" |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 return; | 177 return; |
| 178 watcher->ActivateThreadWatching(); | 178 watcher->ActivateThreadWatching(); |
| 179 } | 179 } |
| 180 | 180 |
| 181 void ThreadWatcher::ActivateThreadWatching() { | 181 void ThreadWatcher::ActivateThreadWatching() { |
| 182 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 182 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 183 if (active_) return; | 183 if (active_) return; |
| 184 active_ = true; | 184 active_ = true; |
| 185 ping_count_ = unresponsive_threshold_; | 185 ping_count_ = unresponsive_threshold_; |
| 186 ResetHangCounters(); | 186 ResetHangCounters(); |
| 187 MessageLoop::current()->PostTask( | 187 base::MessageLoop::current()->PostTask( |
| 188 FROM_HERE, | 188 FROM_HERE, |
| 189 base::Bind(&ThreadWatcher::PostPingMessage, | 189 base::Bind(&ThreadWatcher::PostPingMessage, |
| 190 weak_ptr_factory_.GetWeakPtr())); | 190 weak_ptr_factory_.GetWeakPtr())); |
| 191 } | 191 } |
| 192 | 192 |
| 193 void ThreadWatcher::DeActivateThreadWatching() { | 193 void ThreadWatcher::DeActivateThreadWatching() { |
| 194 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 194 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 195 active_ = false; | 195 active_ = false; |
| 196 ping_count_ = 0; | 196 ping_count_ = 0; |
| 197 weak_ptr_factory_.InvalidateWeakPtrs(); | 197 weak_ptr_factory_.InvalidateWeakPtrs(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 // Send a ping message to the watched thread. Callback will be called on | 233 // Send a ping message to the watched thread. Callback will be called on |
| 234 // the WatchDogThread. | 234 // the WatchDogThread. |
| 235 base::Closure callback( | 235 base::Closure callback( |
| 236 base::Bind(&ThreadWatcher::OnPongMessage, weak_ptr_factory_.GetWeakPtr(), | 236 base::Bind(&ThreadWatcher::OnPongMessage, weak_ptr_factory_.GetWeakPtr(), |
| 237 ping_sequence_number_)); | 237 ping_sequence_number_)); |
| 238 if (watched_loop_->PostTask( | 238 if (watched_loop_->PostTask( |
| 239 FROM_HERE, | 239 FROM_HERE, |
| 240 base::Bind(&ThreadWatcher::OnPingMessage, thread_id_, | 240 base::Bind(&ThreadWatcher::OnPingMessage, thread_id_, |
| 241 callback))) { | 241 callback))) { |
| 242 // Post a task to check the responsiveness of watched thread. | 242 // Post a task to check the responsiveness of watched thread. |
| 243 MessageLoop::current()->PostDelayedTask( | 243 base::MessageLoop::current()->PostDelayedTask( |
| 244 FROM_HERE, | 244 FROM_HERE, |
| 245 base::Bind(&ThreadWatcher::OnCheckResponsiveness, | 245 base::Bind(&ThreadWatcher::OnCheckResponsiveness, |
| 246 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), | 246 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), |
| 247 unresponsive_time_); | 247 unresponsive_time_); |
| 248 } else { | 248 } else { |
| 249 // Watched thread might have gone away, stop watching it. | 249 // Watched thread might have gone away, stop watching it. |
| 250 DeActivateThreadWatching(); | 250 DeActivateThreadWatching(); |
| 251 } | 251 } |
| 252 } | 252 } |
| 253 | 253 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 269 | 269 |
| 270 // Increment sequence number for the next ping message to indicate watched | 270 // Increment sequence number for the next ping message to indicate watched |
| 271 // thread is responsive. | 271 // thread is responsive. |
| 272 ++ping_sequence_number_; | 272 ++ping_sequence_number_; |
| 273 | 273 |
| 274 // If we have stopped watching or if the user is idle, then stop sending | 274 // If we have stopped watching or if the user is idle, then stop sending |
| 275 // ping messages. | 275 // ping messages. |
| 276 if (!active_ || --ping_count_ <= 0) | 276 if (!active_ || --ping_count_ <= 0) |
| 277 return; | 277 return; |
| 278 | 278 |
| 279 MessageLoop::current()->PostDelayedTask( | 279 base::MessageLoop::current()->PostDelayedTask( |
| 280 FROM_HERE, | 280 FROM_HERE, |
| 281 base::Bind(&ThreadWatcher::PostPingMessage, | 281 base::Bind(&ThreadWatcher::PostPingMessage, |
| 282 weak_ptr_factory_.GetWeakPtr()), | 282 weak_ptr_factory_.GetWeakPtr()), |
| 283 sleep_time_); | 283 sleep_time_); |
| 284 } | 284 } |
| 285 | 285 |
| 286 void ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { | 286 void ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { |
| 287 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 287 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 288 // If we have stopped watching then consider thread as responding. | 288 // If we have stopped watching then consider thread as responding. |
| 289 if (!active_) { | 289 if (!active_) { |
| 290 responsive_ = true; | 290 responsive_ = true; |
| 291 return; | 291 return; |
| 292 } | 292 } |
| 293 // If the latest ping_sequence_number_ is not same as the ping_sequence_number | 293 // If the latest ping_sequence_number_ is not same as the ping_sequence_number |
| 294 // that is passed in, then we can assume OnPongMessage was called. | 294 // that is passed in, then we can assume OnPongMessage was called. |
| 295 // OnPongMessage increments ping_sequence_number_. | 295 // OnPongMessage increments ping_sequence_number_. |
| 296 if (ping_sequence_number_ != ping_sequence_number) { | 296 if (ping_sequence_number_ != ping_sequence_number) { |
| 297 // Reset unresponsive_count_ to zero because we got a response from the | 297 // Reset unresponsive_count_ to zero because we got a response from the |
| 298 // watched thread. | 298 // watched thread. |
| 299 ResetHangCounters(); | 299 ResetHangCounters(); |
| 300 | 300 |
| 301 responsive_ = true; | 301 responsive_ = true; |
| 302 return; | 302 return; |
| 303 } | 303 } |
| 304 // Record that we got no response from watched thread. | 304 // Record that we got no response from watched thread. |
| 305 GotNoResponse(); | 305 GotNoResponse(); |
| 306 | 306 |
| 307 // Post a task to check the responsiveness of watched thread. | 307 // Post a task to check the responsiveness of watched thread. |
| 308 MessageLoop::current()->PostDelayedTask( | 308 base::MessageLoop::current()->PostDelayedTask( |
| 309 FROM_HERE, | 309 FROM_HERE, |
| 310 base::Bind(&ThreadWatcher::OnCheckResponsiveness, | 310 base::Bind(&ThreadWatcher::OnCheckResponsiveness, |
| 311 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), | 311 weak_ptr_factory_.GetWeakPtr(), ping_sequence_number_), |
| 312 unresponsive_time_); | 312 unresponsive_time_); |
| 313 responsive_ = false; | 313 responsive_ = false; |
| 314 } | 314 } |
| 315 | 315 |
| 316 void ThreadWatcher::Initialize() { | 316 void ThreadWatcher::Initialize() { |
| 317 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 317 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 318 ThreadWatcherList::Register(this); | 318 ThreadWatcherList::Register(this); |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 } | 780 } |
| 781 | 781 |
| 782 WatchDogThread::~WatchDogThread() { | 782 WatchDogThread::~WatchDogThread() { |
| 783 Stop(); | 783 Stop(); |
| 784 } | 784 } |
| 785 | 785 |
| 786 // static | 786 // static |
| 787 bool WatchDogThread::CurrentlyOnWatchDogThread() { | 787 bool WatchDogThread::CurrentlyOnWatchDogThread() { |
| 788 base::AutoLock lock(g_watchdog_lock.Get()); | 788 base::AutoLock lock(g_watchdog_lock.Get()); |
| 789 return g_watchdog_thread && | 789 return g_watchdog_thread && |
| 790 g_watchdog_thread->message_loop() == MessageLoop::current(); | 790 g_watchdog_thread->message_loop() == base::MessageLoop::current(); |
| 791 } | 791 } |
| 792 | 792 |
| 793 // static | 793 // static |
| 794 bool WatchDogThread::PostTask(const tracked_objects::Location& from_here, | 794 bool WatchDogThread::PostTask(const tracked_objects::Location& from_here, |
| 795 const base::Closure& task) { | 795 const base::Closure& task) { |
| 796 return PostTaskHelper(from_here, task, base::TimeDelta()); | 796 return PostTaskHelper(from_here, task, base::TimeDelta()); |
| 797 } | 797 } |
| 798 | 798 |
| 799 // static | 799 // static |
| 800 bool WatchDogThread::PostDelayedTask(const tracked_objects::Location& from_here, | 800 bool WatchDogThread::PostDelayedTask(const tracked_objects::Location& from_here, |
| 801 const base::Closure& task, | 801 const base::Closure& task, |
| 802 base::TimeDelta delay) { | 802 base::TimeDelta delay) { |
| 803 return PostTaskHelper(from_here, task, delay); | 803 return PostTaskHelper(from_here, task, delay); |
| 804 } | 804 } |
| 805 | 805 |
| 806 // static | 806 // static |
| 807 bool WatchDogThread::PostTaskHelper( | 807 bool WatchDogThread::PostTaskHelper( |
| 808 const tracked_objects::Location& from_here, | 808 const tracked_objects::Location& from_here, |
| 809 const base::Closure& task, | 809 const base::Closure& task, |
| 810 base::TimeDelta delay) { | 810 base::TimeDelta delay) { |
| 811 { | 811 { |
| 812 base::AutoLock lock(g_watchdog_lock.Get()); | 812 base::AutoLock lock(g_watchdog_lock.Get()); |
| 813 | 813 |
| 814 MessageLoop* message_loop = g_watchdog_thread ? | 814 base::MessageLoop* message_loop = g_watchdog_thread ? |
| 815 g_watchdog_thread->message_loop() : NULL; | 815 g_watchdog_thread->message_loop() : NULL; |
| 816 if (message_loop) { | 816 if (message_loop) { |
| 817 message_loop->PostDelayedTask(from_here, task, delay); | 817 message_loop->PostDelayedTask(from_here, task, delay); |
| 818 return true; | 818 return true; |
| 819 } | 819 } |
| 820 } | 820 } |
| 821 | 821 |
| 822 return false; | 822 return false; |
| 823 } | 823 } |
| 824 | 824 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 void StartupTimeBomb::DeleteStartupWatchdog() { | 926 void StartupTimeBomb::DeleteStartupWatchdog() { |
| 927 DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId()); | 927 DCHECK_EQ(thread_id_, base::PlatformThread::CurrentId()); |
| 928 if (startup_watchdog_->IsJoinable()) { | 928 if (startup_watchdog_->IsJoinable()) { |
| 929 // Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns | 929 // Allow the watchdog thread to shutdown on UI. Watchdog thread shutdowns |
| 930 // very fast. | 930 // very fast. |
| 931 base::ThreadRestrictions::SetIOAllowed(true); | 931 base::ThreadRestrictions::SetIOAllowed(true); |
| 932 delete startup_watchdog_; | 932 delete startup_watchdog_; |
| 933 startup_watchdog_ = NULL; | 933 startup_watchdog_ = NULL; |
| 934 return; | 934 return; |
| 935 } | 935 } |
| 936 MessageLoop::current()->PostDelayedTask( | 936 base::MessageLoop::current()->PostDelayedTask( |
| 937 FROM_HERE, | 937 FROM_HERE, |
| 938 base::Bind(&StartupTimeBomb::DeleteStartupWatchdog, | 938 base::Bind(&StartupTimeBomb::DeleteStartupWatchdog, |
| 939 base::Unretained(this)), | 939 base::Unretained(this)), |
| 940 base::TimeDelta::FromSeconds(10)); | 940 base::TimeDelta::FromSeconds(10)); |
| 941 } | 941 } |
| 942 | 942 |
| 943 // static | 943 // static |
| 944 void StartupTimeBomb::DisarmStartupTimeBomb() { | 944 void StartupTimeBomb::DisarmStartupTimeBomb() { |
| 945 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 945 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 946 if (g_startup_timebomb_) | 946 if (g_startup_timebomb_) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 | 980 |
| 981 #if defined(OS_WIN) | 981 #if defined(OS_WIN) |
| 982 // On Windows XP, give twice the time for shutdown. | 982 // On Windows XP, give twice the time for shutdown. |
| 983 if (base::win::GetVersion() <= base::win::VERSION_XP) | 983 if (base::win::GetVersion() <= base::win::VERSION_XP) |
| 984 actual_duration *= 2; | 984 actual_duration *= 2; |
| 985 #endif | 985 #endif |
| 986 | 986 |
| 987 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); | 987 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); |
| 988 shutdown_watchdog_->Arm(); | 988 shutdown_watchdog_->Arm(); |
| 989 } | 989 } |
| OLD | NEW |