Index: chrome/browser/hang_monitor/hung_window_detector.cc |
=================================================================== |
--- chrome/browser/hang_monitor/hung_window_detector.cc (revision 134453) |
+++ chrome/browser/hang_monitor/hung_window_detector.cc (working copy) |
@@ -3,24 +3,41 @@ |
// 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), |
@@ -161,10 +178,23 @@ |
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. |
- CrashDumpAndTerminateHungChildProcess(child_process); |
+ 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); |
child_process.Close(); |
break; |
} |