diff options
-rw-r--r-- | chrome/browser/hang_monitor/hang_crash_dump_win.cc | 45 | ||||
-rw-r--r-- | chrome/browser/hang_monitor/hang_crash_dump_win.h | 14 | ||||
-rw-r--r-- | chrome/browser/hang_monitor/hung_window_detector.cc | 44 | ||||
-rw-r--r-- | chrome/browser/ui/hung_plugin_tab_helper.cc | 12 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 7 |
5 files changed, 81 insertions, 41 deletions
diff --git a/chrome/browser/hang_monitor/hang_crash_dump_win.cc b/chrome/browser/hang_monitor/hang_crash_dump_win.cc new file mode 100644 index 0000000..ce02d81 --- /dev/null +++ b/chrome/browser/hang_monitor/hang_crash_dump_win.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2012 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/hang_monitor/hang_crash_dump_win.h" + +#include "chrome/common/chrome_constants.h" +#include "content/public/common/result_codes.h" + +namespace { + +// This function will be called via an injected thread in the hung plugin +// process. calling DumpProcessWithoutCrash causes breakpad to capture a dump of +// the process. +DWORD WINAPI HungPluginDumpAndExit(void*) { + typedef void (__cdecl *DumpProcessFunction)(); + DumpProcessFunction request_dump = reinterpret_cast<DumpProcessFunction>( + GetProcAddress(GetModuleHandle(chrome::kBrowserProcessExecutableName), + "DumpProcessWithoutCrash")); + if (request_dump) + request_dump(); + return 0; +} + +// How long do we wait for the terminated thread or process to die (in ms) +static const int kTerminateTimeoutMS = 2000; + +// How long do we wait for the crash to be generated (in ms). +static const int kGenerateDumpTimeoutMS = 10000; + +} // namespace + +void CrashDumpAndTerminateHungChildProcess(HANDLE hprocess) { + // Before terminating the process we try collecting a dump. Which + // a transient thread in the child process will do for us. + HANDLE remote_thread = CreateRemoteThread(hprocess, NULL, 0, + &HungPluginDumpAndExit, 0, 0, NULL); + if (remote_thread) { + WaitForSingleObject(remote_thread, kGenerateDumpTimeoutMS); + CloseHandle(remote_thread); + } + + TerminateProcess(hprocess, content::RESULT_CODE_HUNG); + WaitForSingleObject(hprocess, kTerminateTimeoutMS); +} diff --git a/chrome/browser/hang_monitor/hang_crash_dump_win.h b/chrome/browser/hang_monitor/hang_crash_dump_win.h new file mode 100644 index 0000000..d3b6629 --- /dev/null +++ b/chrome/browser/hang_monitor/hang_crash_dump_win.h @@ -0,0 +1,14 @@ +// Copyright (c) 2012 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. + +#ifndef CHROME_BROWSER_HANG_MONITOR_HANG_CRASH_DUMP_WIN_H_ +#define CHROME_BROWSER_HANG_MONITOR_HANG_CRASH_DUMP_WIN_H_ + +#include <windows.h> + +// Causes the given child process to generate a crash dump and terminates the +// process. +void CrashDumpAndTerminateHungChildProcess(HANDLE hprocess); + +#endif // CHROME_BROWSER_HANG_MONITOR_HANG_CRASH_DUMP_WIN_H_ diff --git a/chrome/browser/hang_monitor/hung_window_detector.cc b/chrome/browser/hang_monitor/hung_window_detector.cc index 3b6ad9b..d69ec68 100644 --- a/chrome/browser/hang_monitor/hung_window_detector.cc +++ b/chrome/browser/hang_monitor/hung_window_detector.cc @@ -3,41 +3,24 @@ // found in the LICENSE file. #include "chrome/browser/hang_monitor/hung_window_detector.h" -#include "chrome/common/chrome_constants.h" #include <windows.h> #include <atlbase.h> #include "base/logging.h" +#include "chrome/browser/hang_monitor/hang_crash_dump_win.h" #include "content/public/common/result_codes.h" +namespace { + // How long do we wait for the terminated thread or process to die (in ms) static const int kTerminateTimeout = 2000; -// How long do we wait for the crash to be generated (in ms). -static const int kGenerateDumpTimeout = 10000; + +} // namespace const wchar_t HungWindowDetector::kHungChildWindowTimeout[] = L"Chrome_HungChildWindowTimeout"; -namespace { - -typedef void (*DumpProcessWithoutCrashFn)(); -// This function will be called via an injected thread in the hung plugin -// process. calling DumpProcessWithoutCrash causes breakpad to capture a dump of -// the process. -DWORD WINAPI HungPluginDumpAndExit(void*) { - typedef void (__cdecl *DumpProcessFunction)(); - DumpProcessFunction request_dump = reinterpret_cast<DumpProcessFunction>( - ::GetProcAddress(::GetModuleHandle( - chrome::kBrowserProcessExecutableName), - "DumpProcessWithoutCrash")); - if (request_dump) - request_dump(); - return 0; -} - -} // namespace - HungWindowDetector::HungWindowDetector(HungWindowNotification* notification) : notification_(notification), top_level_window_(NULL), @@ -178,23 +161,10 @@ bool HungWindowDetector::CheckChildWindow(HWND child_window) { if (process_id_check != child_window_process_id) { break; } + // Before terminating the process we try collecting a dump. Which // a transient thread in the child process will do for us. - HANDLE remote_thread = - CreateRemoteThread(child_process, - NULL, - 0, - &HungPluginDumpAndExit, - 0, - 0, - NULL); - if (remote_thread) { - WaitForSingleObject(remote_thread, kGenerateDumpTimeout); - CloseHandle(remote_thread); - } - - TerminateProcess(child_process, content::RESULT_CODE_HUNG); - WaitForSingleObject(child_process, kTerminateTimeout); + CrashDumpAndTerminateHungChildProcess(child_process); child_process.Close(); break; } diff --git a/chrome/browser/ui/hung_plugin_tab_helper.cc b/chrome/browser/ui/hung_plugin_tab_helper.cc index 0b748dd..a16e4f7 100644 --- a/chrome/browser/ui/hung_plugin_tab_helper.cc +++ b/chrome/browser/ui/hung_plugin_tab_helper.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/process_util.h" +#include "build/build_config.h" #include "chrome/browser/infobars/infobar_tab_helper.h" #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" @@ -21,6 +22,10 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#if defined(OS_WIN) +#include "chrome/browser/hang_monitor/hang_crash_dump_win.h" +#endif + namespace { // Delay in seconds before re-showing the hung plugin message. This will be @@ -40,10 +45,11 @@ void KillPluginOnIOThread(int child_id) { while (!iter.Done()) { const content::ChildProcessData& data = iter.GetData(); if (data.id == child_id) { - // TODO(brettw) bug 123021: it might be nice to do some stuff to capture - // a stack. The NPAPI Windows hang monitor does some cool stuff in - // hung_window_detector.cc. +#if defined(OS_WIN) + CrashDumpAndTerminateHungChildProcess(data.handle); +#else base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false); +#endif break; } ++iter; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 792a2e0..4e40945 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1063,6 +1063,8 @@ 'browser/gpu_blacklist.h', 'browser/gpu_util.cc', 'browser/gpu_util.h', + 'browser/hang_monitor/hang_crash_dump_win.cc', + 'browser/hang_monitor/hang_crash_dump_win.h', 'browser/hang_monitor/hung_plugin_action.cc', 'browser/hang_monitor/hung_plugin_action.h', 'browser/hang_monitor/hung_window_detector.cc', @@ -4261,7 +4263,10 @@ ['exclude', '^browser/first_run/try_chrome_dialog_view.h'], ['exclude', '^browser/google/google_update.cc'], ['exclude', '^browser/google/google_update.h'], - ['exclude', '^browser/hang_monitor/'], + ['exclude', '^browser/hang_monitor/hung_plugin_action.cc'], + ['exclude', '^browser/hang_monitor/hung_plugin_action.h'], + ['exclude', '^browser/hang_monitor/hung_window_detector.cc'], + ['exclude', '^browser/hang_monitor/hung_window_detector.h'], ['exclude', '^browser/renderer_host/render_widget_host_view_views*'], ['exclude', '^browser/tab_contents/web_drag_bookmark_handler_win.cc'], ['exclude', '^browser/tab_contents/web_drag_bookmark_handler_win.h'], |