// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/metrics/thread_watcher_report_hang.h" // We disable optimizations for the whole file so the compiler doesn't merge // them all together. MSVC_DISABLE_OPTIMIZE() MSVC_PUSH_DISABLE_WARNING(4748) #include "base/debug/debugger.h" #include "base/debug/dump_without_crashing.h" #include "build/build_config.h" namespace metrics { // The following are unique function names for forcing the crash when a thread // is unresponsive. This makes it possible to tell from the callstack alone what // thread was unresponsive. NOINLINE void ReportThreadHang() { volatile const char* inhibit_comdat = __FUNCTION__; ALLOW_UNUSED_LOCAL(inhibit_comdat); #if defined(NDEBUG) base::debug::DumpWithoutCrashing(); #else base::debug::BreakDebugger(); #endif } #if !defined(OS_ANDROID) || !defined(NDEBUG) NOINLINE void StartupHang() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); // TODO(rtenneti): http://crbug.com/440885 enable crashing after fixing false // positive startup hang data. // ReportThreadHang(); } #endif // OS_ANDROID NOINLINE void ShutdownHang() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_UI() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_DB() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_FILE() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_FILE_USER_BLOCKING() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_PROCESS_LAUNCHER() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_CACHE() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void ThreadUnresponsive_IO() { volatile int inhibit_comdat = __LINE__; ALLOW_UNUSED_LOCAL(inhibit_comdat); ReportThreadHang(); } NOINLINE void CrashBecauseThreadWasUnresponsive(int thread_id) { // TODO(rtenneti): The following is a temporary change to check thread_id // numbers explicitly so that we will have minimum code. Will change after the // test run to use content::BrowserThread::ID enum. if (thread_id == 0) return ThreadUnresponsive_UI(); else if (thread_id == 1) return ThreadUnresponsive_DB(); else if (thread_id == 2) return ThreadUnresponsive_FILE(); else if (thread_id == 3) return ThreadUnresponsive_FILE_USER_BLOCKING(); else if (thread_id == 4) return ThreadUnresponsive_PROCESS_LAUNCHER(); else if (thread_id == 5) return ThreadUnresponsive_CACHE(); else if (thread_id == 6) return ThreadUnresponsive_IO(); } } // namespace metrics MSVC_POP_WARNING() MSVC_ENABLE_OPTIMIZE();