Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(571)

Side by Side Diff: chrome/browser/metrics/thread_watcher.cc

Issue 12183008: ThreadWatcher - Added jankiness monitor for FILE thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/alias.h" 11 #include "base/debug/alias.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/string_split.h" 13 #include "base/string_split.h"
14 #include "base/stringprintf.h"
14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_tokenizer.h" 16 #include "base/strings/string_tokenizer.h"
16 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
17 #include "build/build_config.h" 18 #include "build/build_config.h"
18 #include "chrome/browser/metrics/metrics_service.h" 19 #include "chrome/browser/metrics/metrics_service.h"
19 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/chrome_version_info.h" 21 #include "chrome/common/chrome_version_info.h"
21 #include "chrome/common/dump_without_crashing.h" 22 #include "chrome/common/dump_without_crashing.h"
22 #include "chrome/common/logging_chrome.h" 23 #include "chrome/common/logging_chrome.h"
23 24
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 ThreadWatcherList* ThreadWatcherList::g_thread_watcher_list_ = NULL; 402 ThreadWatcherList* ThreadWatcherList::g_thread_watcher_list_ = NULL;
402 // static 403 // static
403 const int ThreadWatcherList::kSleepSeconds = 1; 404 const int ThreadWatcherList::kSleepSeconds = 1;
404 // static 405 // static
405 const int ThreadWatcherList::kUnresponsiveSeconds = 2; 406 const int ThreadWatcherList::kUnresponsiveSeconds = 2;
406 // static 407 // static
407 const int ThreadWatcherList::kUnresponsiveCount = 9; 408 const int ThreadWatcherList::kUnresponsiveCount = 9;
408 // static 409 // static
409 const int ThreadWatcherList::kLiveThreadsThreshold = 3; 410 const int ThreadWatcherList::kLiveThreadsThreshold = 3;
410 411
412 ThreadWatcherList::CrashDataThresholds::CrashDataThresholds(
413 uint32 live_threads_threshold,
414 uint32 unresponsive_threshold)
415 : live_threads_threshold(live_threads_threshold),
416 unresponsive_threshold(unresponsive_threshold) {
417 }
418
419 ThreadWatcherList::CrashDataThresholds::CrashDataThresholds()
420 : live_threads_threshold(kLiveThreadsThreshold),
421 unresponsive_threshold(kUnresponsiveCount) {
422 }
423
411 // static 424 // static
412 void ThreadWatcherList::StartWatchingAll(const CommandLine& command_line) { 425 void ThreadWatcherList::StartWatchingAll(const CommandLine& command_line) {
413 uint32 unresponsive_threshold; 426 uint32 unresponsive_threshold;
414 CrashOnHangThreadMap crash_on_hang_threads; 427 CrashOnHangThreadMap crash_on_hang_threads;
415 ParseCommandLine(command_line, 428 ParseCommandLine(command_line,
416 &unresponsive_threshold, 429 &unresponsive_threshold,
417 &crash_on_hang_threads); 430 &crash_on_hang_threads);
418 431
419 ThreadWatcherObserver::SetupNotifications( 432 ThreadWatcherObserver::SetupNotifications(
420 base::TimeDelta::FromSeconds(kSleepSeconds * unresponsive_threshold)); 433 base::TimeDelta::FromSeconds(kSleepSeconds * unresponsive_threshold));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); 504 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
492 DCHECK(this == g_thread_watcher_list_); 505 DCHECK(this == g_thread_watcher_list_);
493 g_thread_watcher_list_ = NULL; 506 g_thread_watcher_list_ = NULL;
494 } 507 }
495 508
496 // static 509 // static
497 void ThreadWatcherList::ParseCommandLine( 510 void ThreadWatcherList::ParseCommandLine(
498 const CommandLine& command_line, 511 const CommandLine& command_line,
499 uint32* unresponsive_threshold, 512 uint32* unresponsive_threshold,
500 CrashOnHangThreadMap* crash_on_hang_threads) { 513 CrashOnHangThreadMap* crash_on_hang_threads) {
501 // Determine |unresponsive_threshold| based on switches::kCrashOnHangSeconds. 514 // Initialize |unresponsive_threshold| to a default value.
502 *unresponsive_threshold = kUnresponsiveCount; 515 *unresponsive_threshold = kUnresponsiveCount;
503 516
504 // Increase the unresponsive_threshold on the Stable and Beta channels to 517 // Increase the unresponsive_threshold on the Stable and Beta channels to
505 // reduce the number of crashes due to ThreadWatcher. 518 // reduce the number of crashes due to ThreadWatcher.
506 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 519 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
507 if (channel == chrome::VersionInfo::CHANNEL_STABLE) { 520 if (channel == chrome::VersionInfo::CHANNEL_STABLE) {
508 *unresponsive_threshold *= 4; 521 *unresponsive_threshold *= 4;
509 } else if (channel == chrome::VersionInfo::CHANNEL_BETA) { 522 } else if (channel == chrome::VersionInfo::CHANNEL_BETA) {
510 *unresponsive_threshold *= 2; 523 *unresponsive_threshold *= 2;
511 } 524 }
512 525
513 #if defined(OS_WIN) 526 #if defined(OS_WIN)
514 // For Windows XP (old systems), double the unresponsive_threshold to give 527 // For Windows XP (old systems), double the unresponsive_threshold to give
515 // the OS a chance to schedule UI/IO threads a time slice to respond with a 528 // the OS a chance to schedule UI/IO threads a time slice to respond with a
516 // pong message (to get around limitations with the OS). 529 // pong message (to get around limitations with the OS).
517 if (base::win::GetVersion() <= base::win::VERSION_XP) 530 if (base::win::GetVersion() <= base::win::VERSION_XP)
518 *unresponsive_threshold *= 2; 531 *unresponsive_threshold *= 2;
519 #endif 532 #endif
520 533
521 std::string crash_on_hang_seconds = 534 uint32 crash_seconds = *unresponsive_threshold * kUnresponsiveSeconds;
522 command_line.GetSwitchValueASCII(switches::kCrashOnHangSeconds);
523 if (!crash_on_hang_seconds.empty()) {
524 int crash_seconds = atoi(crash_on_hang_seconds.c_str());
525 if (crash_seconds > 0) {
526 *unresponsive_threshold = static_cast<uint32>(
527 ceil(static_cast<float>(crash_seconds) / kUnresponsiveSeconds));
528 }
529 }
530
531 std::string crash_on_hang_thread_names; 535 std::string crash_on_hang_thread_names;
532
533 // Default to crashing the browser if UI or IO threads are not responsive
534 // except in stable channel.
535 if (channel == chrome::VersionInfo::CHANNEL_STABLE)
536 crash_on_hang_thread_names = "";
537 else
538 crash_on_hang_thread_names = "UI:3,IO:9";
539
540 bool has_command_line_overwrite = false; 536 bool has_command_line_overwrite = false;
541 if (command_line.HasSwitch(switches::kCrashOnHangThreads)) { 537 if (command_line.HasSwitch(switches::kCrashOnHangThreads)) {
542 crash_on_hang_thread_names = 538 crash_on_hang_thread_names =
543 command_line.GetSwitchValueASCII(switches::kCrashOnHangThreads); 539 command_line.GetSwitchValueASCII(switches::kCrashOnHangThreads);
544 has_command_line_overwrite = true; 540 has_command_line_overwrite = true;
541 } else if (channel != chrome::VersionInfo::CHANNEL_STABLE) {
542 // Default to crashing the browser if UI or IO or FILE threads are not
543 // responsive except in stable channel.
544 crash_on_hang_thread_names = base::StringPrintf(
545 "UI:%d:%d,IO:%d:%d,FILE:%d:%d",
546 kLiveThreadsThreshold, crash_seconds,
547 kLiveThreadsThreshold, crash_seconds,
548 kLiveThreadsThreshold, crash_seconds * 5);
545 } 549 }
546 base::StringTokenizer tokens(crash_on_hang_thread_names, ","); 550
547 std::vector<std::string> values; 551 ParseCommandLineCrashOnHangThreads(crash_on_hang_thread_names,
548 while (tokens.GetNext()) { 552 kLiveThreadsThreshold,
549 const std::string& token = tokens.token(); 553 crash_seconds,
550 base::SplitString(token, ':', &values); 554 crash_on_hang_threads);
551 if (values.size() != 2)
552 continue;
553 std::string thread_name = values[0];
554 uint32 live_threads_threshold;
555 if (!base::StringToUint(values[1], &live_threads_threshold))
556 continue;
557 CrashOnHangThreadMap::iterator it =
558 crash_on_hang_threads->find(thread_name);
559 if (crash_on_hang_threads->end() == it)
560 (*crash_on_hang_threads)[thread_name] = live_threads_threshold;
561 }
562 555
563 if (channel != chrome::VersionInfo::CHANNEL_CANARY || 556 if (channel != chrome::VersionInfo::CHANNEL_CANARY ||
564 has_command_line_overwrite) { 557 has_command_line_overwrite) {
565 return; 558 return;
566 } 559 }
567 560
568 // Set up a field trial for 10% of the users to crash if IO thread is not 561 // Set up a field trial for 10% of the users to crash if IO thread is not
569 // responsive. 562 // responsive.
570 CrashOnHangThreadMap::iterator it = crash_on_hang_threads->find("IO"); 563 CrashOnHangThreadMap::iterator it = crash_on_hang_threads->find("IO");
571 if (crash_on_hang_threads->end() == it) 564 if (crash_on_hang_threads->end() == it)
572 return; 565 return;
573 566
574 scoped_refptr<base::FieldTrial> field_trial( 567 scoped_refptr<base::FieldTrial> field_trial(
575 base::FieldTrialList::FactoryGetFieldTrial( 568 base::FieldTrialList::FactoryGetFieldTrial(
576 "ThreadWatcher", 100, "default_hung_threads", 569 "ThreadWatcher", 100, "default_hung_threads",
577 2013, 10, 30, NULL)); 570 2013, 10, 30, NULL));
578 int io_hung_thread_group = field_trial->AppendGroup("io_hung_thread", 10); 571 int io_hung_thread_group = field_trial->AppendGroup("io_hung_thread", 10);
579 if (field_trial->group() == io_hung_thread_group) 572 if (field_trial->group() == io_hung_thread_group) {
580 it->second = INT_MAX; // Crash anytime IO thread hangs. 573 // Crash anytime IO thread hangs.
574 it->second.live_threads_threshold = INT_MAX;
575 }
576 }
577
578 // static
579 void ThreadWatcherList::ParseCommandLineCrashOnHangThreads(
580 const std::string& crash_on_hang_thread_names,
581 uint32 default_live_threads_threshold,
582 uint32 default_crash_seconds,
583 CrashOnHangThreadMap* crash_on_hang_threads) {
584 base::StringTokenizer tokens(crash_on_hang_thread_names, ",");
585 std::vector<std::string> values;
586 while (tokens.GetNext()) {
587 const std::string& token = tokens.token();
588 base::SplitString(token, ':', &values);
589 std::string thread_name = values[0];
590
591 uint32 live_threads_threshold = default_live_threads_threshold;
592 uint32 crash_seconds = default_crash_seconds;
593 if (values.size() >= 2 &&
594 (!base::StringToUint(values[1], &live_threads_threshold))) {
595 continue;
596 }
597 if (values.size() >= 3 &&
598 (!base::StringToUint(values[2], &crash_seconds))) {
599 continue;
600 }
601 uint32 unresponsive_threshold = static_cast<uint32>(
602 ceil(static_cast<float>(crash_seconds) / kUnresponsiveSeconds));
603
604 CrashDataThresholds crash_data(live_threads_threshold,
605 unresponsive_threshold);
606 // Use the last specifier.
607 (*crash_on_hang_threads)[thread_name] = crash_data;
608 }
581 } 609 }
582 610
583 // static 611 // static
584 void ThreadWatcherList::InitializeAndStartWatching( 612 void ThreadWatcherList::InitializeAndStartWatching(
585 uint32 unresponsive_threshold, 613 uint32 unresponsive_threshold,
586 const CrashOnHangThreadMap& crash_on_hang_threads) { 614 const CrashOnHangThreadMap& crash_on_hang_threads) {
587 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); 615 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
588 616
589 ThreadWatcherList* thread_watcher_list = new ThreadWatcherList(); 617 ThreadWatcherList* thread_watcher_list = new ThreadWatcherList();
590 CHECK(thread_watcher_list); 618 CHECK(thread_watcher_list);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 uint32 unresponsive_threshold, 651 uint32 unresponsive_threshold,
624 const CrashOnHangThreadMap& crash_on_hang_threads) { 652 const CrashOnHangThreadMap& crash_on_hang_threads) {
625 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); 653 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
626 654
627 CrashOnHangThreadMap::const_iterator it = 655 CrashOnHangThreadMap::const_iterator it =
628 crash_on_hang_threads.find(thread_name); 656 crash_on_hang_threads.find(thread_name);
629 bool crash_on_hang = false; 657 bool crash_on_hang = false;
630 uint32 live_threads_threshold = 0; 658 uint32 live_threads_threshold = 0;
631 if (it != crash_on_hang_threads.end()) { 659 if (it != crash_on_hang_threads.end()) {
632 crash_on_hang = true; 660 crash_on_hang = true;
633 live_threads_threshold = it->second; 661 live_threads_threshold = it->second.live_threads_threshold;
662 unresponsive_threshold = it->second.unresponsive_threshold;
634 } 663 }
635 664
636 ThreadWatcher::StartWatching( 665 ThreadWatcher::StartWatching(
637 ThreadWatcher::WatchingParams(thread_id, 666 ThreadWatcher::WatchingParams(thread_id,
638 thread_name, 667 thread_name,
639 sleep_time, 668 sleep_time,
640 unresponsive_time, 669 unresponsive_time,
641 unresponsive_threshold, 670 unresponsive_threshold,
642 crash_on_hang, 671 crash_on_hang,
643 live_threads_threshold)); 672 live_threads_threshold));
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 969
941 #if defined(OS_WIN) 970 #if defined(OS_WIN)
942 // On Windows XP, give twice the time for shutdown. 971 // On Windows XP, give twice the time for shutdown.
943 if (base::win::GetVersion() <= base::win::VERSION_XP) 972 if (base::win::GetVersion() <= base::win::VERSION_XP)
944 actual_duration *= 2; 973 actual_duration *= 2;
945 #endif 974 #endif
946 975
947 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); 976 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration);
948 shutdown_watchdog_->Arm(); 977 shutdown_watchdog_->Arm();
949 } 978 }
OLDNEW
« no previous file with comments | « chrome/browser/metrics/thread_watcher.h ('k') | chrome/browser/metrics/thread_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698