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
3// found in the LICENSE file.
4
5#include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
6
7#include "base/logging.h"
8#include "chrome/common/chrome_constants.h"
9#include "content/public/common/result_codes.h"
10
11namespace {
12
13// How long do we wait for the terminated thread or process to die (in ms)
14static const int kTerminateTimeoutMS = 2000;
15
16// How long do we wait for the crash to be generated (in ms).
17static const int kGenerateDumpTimeoutMS = 10000;
18
19}  // namespace
20
21void CrashDumpAndTerminateHungChildProcess(HANDLE hprocess) {
22  // Before terminating the process we try collecting a dump. Which
23  // a transient thread in the child process will do for us.
24  typedef HANDLE (__cdecl *DumpFunction)(HANDLE);
25  static DumpFunction request_dump = NULL;
26  if (!request_dump) {
27    request_dump = reinterpret_cast<DumpFunction>(GetProcAddress(
28        GetModuleHandle(chrome::kBrowserProcessExecutableName),
29            "InjectDumpProcessWithoutCrash"));
30    DCHECK(request_dump) << "Failed loading DumpProcessWithoutCrash: error " <<
31        GetLastError();
32  }
33
34  if (request_dump) {
35    HANDLE remote_thread = request_dump(hprocess);
36    DCHECK(remote_thread) << "Failed creating remote thread: error " <<
37        GetLastError();
38    if (remote_thread) {
39      WaitForSingleObject(remote_thread, kGenerateDumpTimeoutMS);
40      CloseHandle(remote_thread);
41    }
42  }
43
44  TerminateProcess(hprocess, content::RESULT_CODE_HUNG);
45  WaitForSingleObject(hprocess, kTerminateTimeoutMS);
46}
47
48void CrashDumpForHangDebugging(HANDLE hprocess) {
49  if (hprocess == GetCurrentProcess()) {
50    typedef void (__cdecl *DumpFunction)();
51    DumpFunction request_dump = reinterpret_cast<DumpFunction>(GetProcAddress(
52        GetModuleHandle(chrome::kBrowserProcessExecutableName),
53        "DumpProcessWithoutCrash"));
54    DCHECK(request_dump) << "Failed loading DumpProcessWithoutCrash: error " <<
55        GetLastError();
56    if (request_dump)
57      request_dump();
58  } else {
59    typedef HANDLE (__cdecl *DumpFunction)(HANDLE);
60    DumpFunction request_dump = reinterpret_cast<DumpFunction>(GetProcAddress(
61        GetModuleHandle(chrome::kBrowserProcessExecutableName),
62        "InjectDumpForHangDebugging"));
63    DCHECK(request_dump) << "Failed loading InjectDumpForHangDebugging: error "
64                         << GetLastError();
65    if (request_dump) {
66      HANDLE remote_thread = request_dump(hprocess);
67      DCHECK(remote_thread) << "Failed creating remote thread: error " <<
68          GetLastError();
69      if (remote_thread) {
70        WaitForSingleObject(remote_thread, kGenerateDumpTimeoutMS);
71        CloseHandle(remote_thread);
72      }
73    }
74  }
75}
76