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