Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: components/crash/content/app/fallback_crash_handler_launcher_win.cc

Issue 2596463002: A simple, practically zero cost fallback crash handler for Crashpad handler process. (Closed)
Patch Set: On 64 bit systems, pointers are large - doofus. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "components/crash/content/app/fallback_crash_handler_launcher_win.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/win/win_util.h"
10
11 namespace crash_reporter {
12
13 namespace {
14
15 // The number of characters reserved at the tail of the command line for the
16 // thread ID parameter.
17 const size_t kCommandLineTailSize = 32;
18
19 } // namespace
20
21 FallbackCrashHandlerLauncher::FallbackCrashHandlerLauncher() {
22 memset(&exception_pointers_, 0, sizeof(exception_pointers_));
23 }
24
25 FallbackCrashHandlerLauncher::~FallbackCrashHandlerLauncher() {}
26
27 bool FallbackCrashHandlerLauncher::Initialize(
28 const base::CommandLine& program,
29 const base::FilePath& crashpad_database) {
30 // Open an inheritable handle to self. This will be inherited to the handler.
31 const DWORD kAccessMask =
32 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE;
33 self_process_handle_.Set(
34 OpenProcess(kAccessMask, TRUE, ::GetCurrentProcessId()));
35 if (!self_process_handle_.IsValid())
36 return false;
37
38 // Setup the startup info for inheriting the self process handle into the
39 // fallback crash handler.
40 if (!startup_info_.InitializeProcThreadAttributeList(1))
41 return false;
42
43 HANDLE raw_self_process_handle = self_process_handle_.Get();
44 if (!startup_info_.UpdateProcThreadAttribute(
45 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &raw_self_process_handle,
46 sizeof(raw_self_process_handle))) {
47 return false;
48 }
49
50 // Build the command line from a copy of the command line passed in.
51 base::CommandLine cmd_line(program);
52 cmd_line.AppendSwitchPath("database", crashpad_database);
53 cmd_line.AppendSwitchASCII(
54 "exception-pointers",
55 base::Uint64ToString(reinterpret_cast<uintptr_t>(&exception_pointers_)));
56 cmd_line.AppendSwitchASCII(
57 "process", base::UintToString(
58 base::win::HandleToUint32(self_process_handle_.Get())));
59
60 std::wstring str_cmd_line = cmd_line.GetCommandLineString();
61
62 // Append the - for now abortive - thread argument manually.
63 str_cmd_line.append(L" --thread=");
64 // Store the command line string for easy use later.
65 cmd_line_.assign(str_cmd_line.begin(), str_cmd_line.end());
66
67 // Resize the vector to reserve space for the thread ID.
68 cmd_line_.resize(cmd_line_.size() + kCommandLineTailSize, '\0');
69
70 return true;
71 }
72
73 DWORD FallbackCrashHandlerLauncher::LaunchAndWaitForHandler(
74 EXCEPTION_POINTERS* exception_pointers) {
75 DCHECK(!cmd_line_.empty());
76 DCHECK_EQ('=', cmd_line_[cmd_line_.size() - kCommandLineTailSize - 1]);
77 // This program has crashed. Try and not use anything but the stack.
78
79 // Append the current thread's ID to the command line in-place.
80 int chars_appended = wsprintf(&cmd_line_.back() - kCommandLineTailSize + 1,
81 L"%d", GetCurrentThreadId());
82 DCHECK_GT(static_cast<int>(kCommandLineTailSize), chars_appended);
83
84 // Copy the exception pointers to our member variable, whose address is
85 // already baked into the command line.
86 exception_pointers_ = *exception_pointers;
87
88 // Launch the pre-cooked command line.
89
90 PROCESS_INFORMATION process_info = {};
91 if (!CreateProcess(nullptr, // Application name.
92 &cmd_line_[0], // Command line.
93 nullptr, // Process attributes.
94 nullptr, // Thread attributes.
95 true, // Inherit handles.
96 0, // Creation flags.
97 nullptr, // Environment.
98 nullptr, // Current directory.
99 startup_info_.startup_info(), // Startup info.
100 &process_info)) {
101 return GetLastError();
102 }
103
104 // Wait on the fallback crash handler process. The expectation is that this
105 // will never return, as the fallback crash handler will terminate this
106 // process. For testing, and full-on belt and suspenders, cover for this
107 // returning.
108 DWORD error = WaitForSingleObject(process_info.hProcess, INFINITE);
109 if (error != WAIT_OBJECT_0) {
110 // This should never happen, barring handle abuse.
111 // TODO(siggi): Record an UMA metric here.
112 NOTREACHED();
113 error = GetLastError();
114 } else {
115 // On successful wait, return the exit code of the fallback crash handler
116 // process.
117 if (!GetExitCodeProcess(process_info.hProcess, &error)) {
118 // This should never happen, barring handle abuse.
119 NOTREACHED();
120 error = GetLastError();
121 }
122 }
123
124 // Close the handles returned from CreateProcess.
125 CloseHandle(process_info.hProcess);
126 CloseHandle(process_info.hThread);
127
128 return error;
129 }
130
131 } // namespace crash_reporter
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698