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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 bool ThreadWatcher::IsVeryUnresponsive() { | 402 bool ThreadWatcher::IsVeryUnresponsive() { |
403 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 403 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
404 return unresponsive_count_ >= unresponsive_threshold_; | 404 return unresponsive_count_ >= unresponsive_threshold_; |
405 } | 405 } |
406 | 406 |
407 // ThreadWatcherList methods and members. | 407 // ThreadWatcherList methods and members. |
408 // | 408 // |
409 // static | 409 // static |
410 ThreadWatcherList* ThreadWatcherList::g_thread_watcher_list_ = NULL; | 410 ThreadWatcherList* ThreadWatcherList::g_thread_watcher_list_ = NULL; |
411 // static | 411 // static |
| 412 bool ThreadWatcherList::g_stopped_ = false; |
| 413 // static |
412 const int ThreadWatcherList::kSleepSeconds = 1; | 414 const int ThreadWatcherList::kSleepSeconds = 1; |
413 // static | 415 // static |
414 const int ThreadWatcherList::kUnresponsiveSeconds = 2; | 416 const int ThreadWatcherList::kUnresponsiveSeconds = 2; |
415 // static | 417 // static |
416 const int ThreadWatcherList::kUnresponsiveCount = 9; | 418 const int ThreadWatcherList::kUnresponsiveCount = 9; |
417 // static | 419 // static |
418 const int ThreadWatcherList::kLiveThreadsThreshold = 2; | 420 const int ThreadWatcherList::kLiveThreadsThreshold = 2; |
419 // static, non-const for tests. | 421 // static, non-const for tests. |
420 int ThreadWatcherList::g_initialize_delay_seconds = 120; | 422 int ThreadWatcherList::g_initialize_delay_seconds = 120; |
421 | 423 |
(...skipping 14 matching lines...) Expand all Loading... |
436 // TODO(rtenneti): Enable ThreadWatcher. | 438 // TODO(rtenneti): Enable ThreadWatcher. |
437 uint32 unresponsive_threshold; | 439 uint32 unresponsive_threshold; |
438 CrashOnHangThreadMap crash_on_hang_threads; | 440 CrashOnHangThreadMap crash_on_hang_threads; |
439 ParseCommandLine(command_line, | 441 ParseCommandLine(command_line, |
440 &unresponsive_threshold, | 442 &unresponsive_threshold, |
441 &crash_on_hang_threads); | 443 &crash_on_hang_threads); |
442 | 444 |
443 ThreadWatcherObserver::SetupNotifications( | 445 ThreadWatcherObserver::SetupNotifications( |
444 base::TimeDelta::FromSeconds(kSleepSeconds * unresponsive_threshold)); | 446 base::TimeDelta::FromSeconds(kSleepSeconds * unresponsive_threshold)); |
445 | 447 |
| 448 WatchDogThread::PostTask( |
| 449 FROM_HERE, |
| 450 base::Bind(&ThreadWatcherList::SetStopped, false)); |
| 451 |
446 WatchDogThread::PostDelayedTask( | 452 WatchDogThread::PostDelayedTask( |
447 FROM_HERE, | 453 FROM_HERE, |
448 base::Bind(&ThreadWatcherList::InitializeAndStartWatching, | 454 base::Bind(&ThreadWatcherList::InitializeAndStartWatching, |
449 unresponsive_threshold, | 455 unresponsive_threshold, |
450 crash_on_hang_threads), | 456 crash_on_hang_threads), |
451 base::TimeDelta::FromSeconds(g_initialize_delay_seconds)); | 457 base::TimeDelta::FromSeconds(g_initialize_delay_seconds)); |
452 } | 458 } |
453 | 459 |
454 // static | 460 // static |
455 void ThreadWatcherList::StopWatchingAll() { | 461 void ThreadWatcherList::StopWatchingAll() { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 (*crash_on_hang_threads)[thread_name] = crash_data; | 634 (*crash_on_hang_threads)[thread_name] = crash_data; |
629 } | 635 } |
630 } | 636 } |
631 | 637 |
632 // static | 638 // static |
633 void ThreadWatcherList::InitializeAndStartWatching( | 639 void ThreadWatcherList::InitializeAndStartWatching( |
634 uint32 unresponsive_threshold, | 640 uint32 unresponsive_threshold, |
635 const CrashOnHangThreadMap& crash_on_hang_threads) { | 641 const CrashOnHangThreadMap& crash_on_hang_threads) { |
636 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 642 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
637 | 643 |
| 644 // This method is deferred in relationship to its StopWatchingAll() |
| 645 // counterpart. If a previous initialization has already happened, or if |
| 646 // stop has been called, there's nothing left to do here. |
| 647 if (g_thread_watcher_list_ || g_stopped_) |
| 648 return; |
| 649 |
638 ThreadWatcherList* thread_watcher_list = new ThreadWatcherList(); | 650 ThreadWatcherList* thread_watcher_list = new ThreadWatcherList(); |
639 CHECK(thread_watcher_list); | 651 CHECK(thread_watcher_list); |
640 | 652 |
641 BrowserThread::PostTask( | 653 BrowserThread::PostTask( |
642 BrowserThread::UI, | 654 BrowserThread::UI, |
643 FROM_HERE, | 655 FROM_HERE, |
644 base::Bind(&StartupTimeBomb::DisarmStartupTimeBomb)); | 656 base::Bind(&StartupTimeBomb::DisarmStartupTimeBomb)); |
645 | 657 |
646 const base::TimeDelta kSleepTime = | 658 const base::TimeDelta kSleepTime = |
647 base::TimeDelta::FromSeconds(kSleepSeconds); | 659 base::TimeDelta::FromSeconds(kSleepSeconds); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 // static | 705 // static |
694 void ThreadWatcherList::DeleteAll() { | 706 void ThreadWatcherList::DeleteAll() { |
695 if (!WatchDogThread::CurrentlyOnWatchDogThread()) { | 707 if (!WatchDogThread::CurrentlyOnWatchDogThread()) { |
696 WatchDogThread::PostTask( | 708 WatchDogThread::PostTask( |
697 FROM_HERE, | 709 FROM_HERE, |
698 base::Bind(&ThreadWatcherList::DeleteAll)); | 710 base::Bind(&ThreadWatcherList::DeleteAll)); |
699 return; | 711 return; |
700 } | 712 } |
701 | 713 |
702 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 714 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 715 |
| 716 SetStopped(true); |
| 717 |
703 if (!g_thread_watcher_list_) | 718 if (!g_thread_watcher_list_) |
704 return; | 719 return; |
705 | 720 |
706 // Delete all thread watcher objects. | 721 // Delete all thread watcher objects. |
707 while (!g_thread_watcher_list_->registered_.empty()) { | 722 while (!g_thread_watcher_list_->registered_.empty()) { |
708 RegistrationList::iterator it = g_thread_watcher_list_->registered_.begin(); | 723 RegistrationList::iterator it = g_thread_watcher_list_->registered_.begin(); |
709 delete it->second; | 724 delete it->second; |
710 g_thread_watcher_list_->registered_.erase(it); | 725 g_thread_watcher_list_->registered_.erase(it); |
711 } | 726 } |
712 | 727 |
713 delete g_thread_watcher_list_; | 728 delete g_thread_watcher_list_; |
714 } | 729 } |
715 | 730 |
716 // static | 731 // static |
717 ThreadWatcher* ThreadWatcherList::Find(const BrowserThread::ID& thread_id) { | 732 ThreadWatcher* ThreadWatcherList::Find(const BrowserThread::ID& thread_id) { |
718 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); | 733 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
719 if (!g_thread_watcher_list_) | 734 if (!g_thread_watcher_list_) |
720 return NULL; | 735 return NULL; |
721 RegistrationList::iterator it = | 736 RegistrationList::iterator it = |
722 g_thread_watcher_list_->registered_.find(thread_id); | 737 g_thread_watcher_list_->registered_.find(thread_id); |
723 if (g_thread_watcher_list_->registered_.end() == it) | 738 if (g_thread_watcher_list_->registered_.end() == it) |
724 return NULL; | 739 return NULL; |
725 return it->second; | 740 return it->second; |
726 } | 741 } |
727 | 742 |
| 743 // static |
| 744 void ThreadWatcherList::SetStopped(bool stopped) { |
| 745 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 746 g_stopped_ = stopped; |
| 747 } |
| 748 |
728 // ThreadWatcherObserver methods and members. | 749 // ThreadWatcherObserver methods and members. |
729 // | 750 // |
730 // static | 751 // static |
731 ThreadWatcherObserver* ThreadWatcherObserver::g_thread_watcher_observer_ = NULL; | 752 ThreadWatcherObserver* ThreadWatcherObserver::g_thread_watcher_observer_ = NULL; |
732 | 753 |
733 ThreadWatcherObserver::ThreadWatcherObserver( | 754 ThreadWatcherObserver::ThreadWatcherObserver( |
734 const base::TimeDelta& wakeup_interval) | 755 const base::TimeDelta& wakeup_interval) |
735 : last_wakeup_time_(base::TimeTicks::Now()), | 756 : last_wakeup_time_(base::TimeTicks::Now()), |
736 wakeup_interval_(wakeup_interval) { | 757 wakeup_interval_(wakeup_interval) { |
737 CHECK(!g_thread_watcher_observer_); | 758 CHECK(!g_thread_watcher_observer_); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 | 1006 |
986 #if defined(OS_WIN) | 1007 #if defined(OS_WIN) |
987 // On Windows XP, give twice the time for shutdown. | 1008 // On Windows XP, give twice the time for shutdown. |
988 if (base::win::GetVersion() <= base::win::VERSION_XP) | 1009 if (base::win::GetVersion() <= base::win::VERSION_XP) |
989 actual_duration *= 2; | 1010 actual_duration *= 2; |
990 #endif | 1011 #endif |
991 | 1012 |
992 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); | 1013 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); |
993 shutdown_watchdog_->Arm(); | 1014 shutdown_watchdog_->Arm(); |
994 } | 1015 } |
OLD | NEW |