| 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/alias.h" | 11 #include "base/debug/alias.h" |
| 12 #include "base/debug/debugger.h" |
| 12 #include "base/debug/dump_without_crashing.h" | 13 #include "base/debug/dump_without_crashing.h" |
| 13 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 14 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
| 15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/string_split.h" | 17 #include "base/strings/string_split.h" |
| 17 #include "base/strings/string_tokenizer.h" | 18 #include "base/strings/string_tokenizer.h" |
| 18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
| 19 #include "base/threading/thread_restrictions.h" | 20 #include "base/threading/thread_restrictions.h" |
| 20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
| 21 #include "chrome/browser/chrome_notification_types.h" | 22 #include "chrome/browser/chrome_notification_types.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 34 | 35 |
| 35 // The following are unique function names for forcing the crash when a thread | 36 // The following are unique function names for forcing the crash when a thread |
| 36 // is unresponsive. This makes it possible to tell from the callstack alone what | 37 // is unresponsive. This makes it possible to tell from the callstack alone what |
| 37 // thread was unresponsive. | 38 // thread was unresponsive. |
| 38 // | 39 // |
| 39 // We disable optimizations for this block of functions so the compiler doesn't | 40 // We disable optimizations for this block of functions so the compiler doesn't |
| 40 // merge them all together. | 41 // merge them all together. |
| 41 MSVC_DISABLE_OPTIMIZE() | 42 MSVC_DISABLE_OPTIMIZE() |
| 42 MSVC_PUSH_DISABLE_WARNING(4748) | 43 MSVC_PUSH_DISABLE_WARNING(4748) |
| 43 | 44 |
| 44 #ifndef NDEBUG | 45 void ReportThreadHang() { |
| 45 int* NullPointer() { | 46 #if defined(NDEBUG) |
| 46 return reinterpret_cast<int*>(NULL); | 47 base::debug::DumpWithoutCrashing(); |
| 47 } | |
| 48 #endif | |
| 49 | |
| 50 void NullPointerCrash(int line_number) { | |
| 51 #ifndef NDEBUG | |
| 52 *NullPointer() = line_number; // Crash. | |
| 53 #else | 48 #else |
| 54 base::debug::DumpWithoutCrashing(); | 49 base::debug::BreakDebugger(); |
| 55 #endif | 50 #endif |
| 56 } | 51 } |
| 57 | 52 |
| 58 #if !defined(OS_ANDROID) || !defined(NDEBUG) | 53 #if !defined(OS_ANDROID) || !defined(NDEBUG) |
| 59 // TODO(rtenneti): Enabled crashing, after getting data. | 54 // TODO(rtenneti): Enabled crashing, after getting data. |
| 60 NOINLINE void StartupCrash() { | 55 NOINLINE void StartupHang() { |
| 61 NullPointerCrash(__LINE__); | 56 ReportThreadHang(); |
| 62 } | 57 } |
| 63 #endif // OS_ANDROID | 58 #endif // OS_ANDROID |
| 64 | 59 |
| 65 NOINLINE void ShutdownCrash() { | 60 NOINLINE void ShutdownHang() { |
| 66 NullPointerCrash(__LINE__); | 61 ReportThreadHang(); |
| 67 } | 62 } |
| 68 | 63 |
| 69 NOINLINE void ThreadUnresponsive_UI() { | 64 NOINLINE void ThreadUnresponsive_UI() { |
| 70 NullPointerCrash(__LINE__); | 65 ReportThreadHang(); |
| 71 } | 66 } |
| 72 | 67 |
| 73 NOINLINE void ThreadUnresponsive_DB() { | 68 NOINLINE void ThreadUnresponsive_DB() { |
| 74 NullPointerCrash(__LINE__); | 69 ReportThreadHang(); |
| 75 } | 70 } |
| 76 | 71 |
| 77 NOINLINE void ThreadUnresponsive_FILE() { | 72 NOINLINE void ThreadUnresponsive_FILE() { |
| 78 NullPointerCrash(__LINE__); | 73 ReportThreadHang(); |
| 79 } | 74 } |
| 80 | 75 |
| 81 NOINLINE void ThreadUnresponsive_FILE_USER_BLOCKING() { | 76 NOINLINE void ThreadUnresponsive_FILE_USER_BLOCKING() { |
| 82 NullPointerCrash(__LINE__); | 77 ReportThreadHang(); |
| 83 } | 78 } |
| 84 | 79 |
| 85 NOINLINE void ThreadUnresponsive_PROCESS_LAUNCHER() { | 80 NOINLINE void ThreadUnresponsive_PROCESS_LAUNCHER() { |
| 86 NullPointerCrash(__LINE__); | 81 ReportThreadHang(); |
| 87 } | 82 } |
| 88 | 83 |
| 89 NOINLINE void ThreadUnresponsive_CACHE() { | 84 NOINLINE void ThreadUnresponsive_CACHE() { |
| 90 NullPointerCrash(__LINE__); | 85 ReportThreadHang(); |
| 91 } | 86 } |
| 92 | 87 |
| 93 NOINLINE void ThreadUnresponsive_IO() { | 88 NOINLINE void ThreadUnresponsive_IO() { |
| 94 NullPointerCrash(__LINE__); | 89 ReportThreadHang(); |
| 95 } | 90 } |
| 96 | 91 |
| 97 MSVC_POP_WARNING() | 92 MSVC_POP_WARNING() |
| 98 MSVC_ENABLE_OPTIMIZE(); | 93 MSVC_ENABLE_OPTIMIZE(); |
| 99 | 94 |
| 100 void CrashBecauseThreadWasUnresponsive(BrowserThread::ID thread_id) { | 95 void CrashBecauseThreadWasUnresponsive(BrowserThread::ID thread_id) { |
| 101 base::debug::Alias(&thread_id); | 96 base::debug::Alias(&thread_id); |
| 102 | 97 |
| 103 switch (thread_id) { | 98 switch (thread_id) { |
| 104 case BrowserThread::UI: | 99 case BrowserThread::UI: |
| (...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 start_time_thread_now_ = base::TimeTicks::IsThreadNowSupported() | 921 start_time_thread_now_ = base::TimeTicks::IsThreadNowSupported() |
| 927 ? base::TimeTicks::ThreadNow() : base::TimeTicks::Now(); | 922 ? base::TimeTicks::ThreadNow() : base::TimeTicks::Now(); |
| 928 #endif // OS_ANDROID | 923 #endif // OS_ANDROID |
| 929 } | 924 } |
| 930 | 925 |
| 931 // Alarm is called if the time expires after an Arm() without someone calling | 926 // Alarm is called if the time expires after an Arm() without someone calling |
| 932 // Disarm(). When Alarm goes off, in release mode we get the crash dump | 927 // Disarm(). When Alarm goes off, in release mode we get the crash dump |
| 933 // without crashing and in debug mode we break into the debugger. | 928 // without crashing and in debug mode we break into the debugger. |
| 934 virtual void Alarm() OVERRIDE { | 929 virtual void Alarm() OVERRIDE { |
| 935 #if !defined(NDEBUG) | 930 #if !defined(NDEBUG) |
| 936 StartupCrash(); | 931 StartupHang(); |
| 937 return; | 932 return; |
| 938 #elif !defined(OS_ANDROID) | 933 #elif !defined(OS_ANDROID) |
| 939 WatchDogThread::PostTask(FROM_HERE, base::Bind(&StartupCrash)); | 934 WatchDogThread::PostTask(FROM_HERE, base::Bind(&StartupHang)); |
| 940 return; | 935 return; |
| 941 #else // Android release: gather stats to figure out when to crash. | 936 #else // Android release: gather stats to figure out when to crash. |
| 942 // TODO(rtenneti): Delete this code, after getting data. | 937 // TODO(rtenneti): Delete this code, after getting data. |
| 943 UMA_HISTOGRAM_TIMES("StartupTimeBomb.Alarm.TimeDuration", | 938 UMA_HISTOGRAM_TIMES("StartupTimeBomb.Alarm.TimeDuration", |
| 944 base::Time::Now() - start_time_clock_); | 939 base::Time::Now() - start_time_clock_); |
| 945 UMA_HISTOGRAM_TIMES("StartupTimeBomb.Alarm.TimeTicksDuration", | 940 UMA_HISTOGRAM_TIMES("StartupTimeBomb.Alarm.TimeTicksDuration", |
| 946 base::TimeTicks::Now() - start_time_monotonic_); | 941 base::TimeTicks::Now() - start_time_monotonic_); |
| 947 if (base::TimeTicks::IsThreadNowSupported()) { | 942 if (base::TimeTicks::IsThreadNowSupported()) { |
| 948 UMA_HISTOGRAM_TIMES( | 943 UMA_HISTOGRAM_TIMES( |
| 949 "StartupTimeBomb.Alarm.ThreadNowDuration", | 944 "StartupTimeBomb.Alarm.ThreadNowDuration", |
| (...skipping 21 matching lines...) Expand all Loading... |
| 971 public: | 966 public: |
| 972 // Constructor specifies how long the ShutdownWatchDogThread will wait before | 967 // Constructor specifies how long the ShutdownWatchDogThread will wait before |
| 973 // alarming. | 968 // alarming. |
| 974 explicit ShutdownWatchDogThread(const base::TimeDelta& duration) | 969 explicit ShutdownWatchDogThread(const base::TimeDelta& duration) |
| 975 : base::Watchdog(duration, "Shutdown watchdog thread", true) { | 970 : base::Watchdog(duration, "Shutdown watchdog thread", true) { |
| 976 } | 971 } |
| 977 | 972 |
| 978 // Alarm is called if the time expires after an Arm() without someone calling | 973 // Alarm is called if the time expires after an Arm() without someone calling |
| 979 // Disarm(). We crash the browser if this method is called. | 974 // Disarm(). We crash the browser if this method is called. |
| 980 virtual void Alarm() OVERRIDE { | 975 virtual void Alarm() OVERRIDE { |
| 981 ShutdownCrash(); | 976 ShutdownHang(); |
| 982 } | 977 } |
| 983 | 978 |
| 984 private: | 979 private: |
| 985 DISALLOW_COPY_AND_ASSIGN(ShutdownWatchDogThread); | 980 DISALLOW_COPY_AND_ASSIGN(ShutdownWatchDogThread); |
| 986 }; | 981 }; |
| 987 } // namespace | 982 } // namespace |
| 988 | 983 |
| 989 // StartupTimeBomb methods and members. | 984 // StartupTimeBomb methods and members. |
| 990 // | 985 // |
| 991 // static | 986 // static |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 | 1075 |
| 1081 #if defined(OS_WIN) | 1076 #if defined(OS_WIN) |
| 1082 // On Windows XP, give twice the time for shutdown. | 1077 // On Windows XP, give twice the time for shutdown. |
| 1083 if (base::win::GetVersion() <= base::win::VERSION_XP) | 1078 if (base::win::GetVersion() <= base::win::VERSION_XP) |
| 1084 actual_duration *= 2; | 1079 actual_duration *= 2; |
| 1085 #endif | 1080 #endif |
| 1086 | 1081 |
| 1087 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); | 1082 shutdown_watchdog_ = new ShutdownWatchDogThread(actual_duration); |
| 1088 shutdown_watchdog_->Arm(); | 1083 shutdown_watchdog_->Arm(); |
| 1089 } | 1084 } |
| OLD | NEW |