Commit e7b9ab2e authored by brettw@chromium.org's avatar brettw@chromium.org

Generate crash dumps when a hung PPAPI plugin is force terminated.

Reland of 134443 with Auro build change.

TEST=none
BUG=123021
Review URL: https://chromiumcodereview.appspot.com/10272007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134537 0039d316-1c4b-4281-b951-d872f2087c98
parent 2fb310fb
// 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);
}
// 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_
...@@ -3,41 +3,24 @@ ...@@ -3,41 +3,24 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/hang_monitor/hung_window_detector.h" #include "chrome/browser/hang_monitor/hung_window_detector.h"
#include "chrome/common/chrome_constants.h"
#include <windows.h> #include <windows.h>
#include <atlbase.h> #include <atlbase.h>
#include "base/logging.h" #include "base/logging.h"
#include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
#include "content/public/common/result_codes.h" #include "content/public/common/result_codes.h"
namespace {
// How long do we wait for the terminated thread or process to die (in ms) // How long do we wait for the terminated thread or process to die (in ms)
static const int kTerminateTimeout = 2000; 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[] = const wchar_t HungWindowDetector::kHungChildWindowTimeout[] =
L"Chrome_HungChildWindowTimeout"; 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) HungWindowDetector::HungWindowDetector(HungWindowNotification* notification)
: notification_(notification), : notification_(notification),
top_level_window_(NULL), top_level_window_(NULL),
...@@ -178,23 +161,10 @@ bool HungWindowDetector::CheckChildWindow(HWND child_window) { ...@@ -178,23 +161,10 @@ bool HungWindowDetector::CheckChildWindow(HWND child_window) {
if (process_id_check != child_window_process_id) { if (process_id_check != child_window_process_id) {
break; break;
} }
// Before terminating the process we try collecting a dump. Which // Before terminating the process we try collecting a dump. Which
// a transient thread in the child process will do for us. // a transient thread in the child process will do for us.
HANDLE remote_thread = CrashDumpAndTerminateHungChildProcess(child_process);
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);
child_process.Close(); child_process.Close();
break; break;
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/process_util.h" #include "base/process_util.h"
#include "build/build_config.h"
#include "chrome/browser/infobars/infobar_tab_helper.h" #include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h" #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
...@@ -21,6 +22,10 @@ ...@@ -21,6 +22,10 @@
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#if defined(OS_WIN)
#include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
#endif
namespace { namespace {
// Delay in seconds before re-showing the hung plugin message. This will be // Delay in seconds before re-showing the hung plugin message. This will be
...@@ -40,10 +45,11 @@ void KillPluginOnIOThread(int child_id) { ...@@ -40,10 +45,11 @@ void KillPluginOnIOThread(int child_id) {
while (!iter.Done()) { while (!iter.Done()) {
const content::ChildProcessData& data = iter.GetData(); const content::ChildProcessData& data = iter.GetData();
if (data.id == child_id) { if (data.id == child_id) {
// TODO(brettw) bug 123021: it might be nice to do some stuff to capture #if defined(OS_WIN)
// a stack. The NPAPI Windows hang monitor does some cool stuff in CrashDumpAndTerminateHungChildProcess(data.handle);
// hung_window_detector.cc. #else
base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false); base::KillProcess(data.handle, content::RESULT_CODE_HUNG, false);
#endif
break; break;
} }
++iter; ++iter;
......
...@@ -1063,6 +1063,8 @@ ...@@ -1063,6 +1063,8 @@
'browser/gpu_blacklist.h', 'browser/gpu_blacklist.h',
'browser/gpu_util.cc', 'browser/gpu_util.cc',
'browser/gpu_util.h', '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.cc',
'browser/hang_monitor/hung_plugin_action.h', 'browser/hang_monitor/hung_plugin_action.h',
'browser/hang_monitor/hung_window_detector.cc', 'browser/hang_monitor/hung_window_detector.cc',
...@@ -4261,7 +4263,10 @@ ...@@ -4261,7 +4263,10 @@
['exclude', '^browser/first_run/try_chrome_dialog_view.h'], ['exclude', '^browser/first_run/try_chrome_dialog_view.h'],
['exclude', '^browser/google/google_update.cc'], ['exclude', '^browser/google/google_update.cc'],
['exclude', '^browser/google/google_update.h'], ['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/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.cc'],
['exclude', '^browser/tab_contents/web_drag_bookmark_handler_win.h'], ['exclude', '^browser/tab_contents/web_drag_bookmark_handler_win.h'],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment