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

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: Fix Clank comparison nit. 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 }
scottmg 2017/01/09 21:10:55 nit; \n before } (or remove the \n after the openi
Sigurður Ásgeirsson 2017/01/09 21:30:38 Done.
19
20 FallbackCrashHandlerLauncher::FallbackCrashHandlerLauncher() {
21 memset(&exception_pointers_, 0, sizeof(exception_pointers_));
22 }
23
24 FallbackCrashHandlerLauncher::~FallbackCrashHandlerLauncher() {}
25
26 bool FallbackCrashHandlerLauncher::Initialize(
27 const base::CommandLine& program,
28 const base::FilePath& crashpad_database) {
29 // Open an inheritable handle to self. This will be inherited to the handler.
30 const DWORD kAccessMask =
31 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE;
32 self_process_handle_.Set(
33 OpenProcess(kAccessMask, TRUE, ::GetCurrentProcessId()));
34 if (!self_process_handle_.IsValid())
35 return false;
36
37 // Setup the startup info for inheriting the self process handle into the
38 // fallback crash handler.
39 if (!startup_info_.InitializeProcThreadAttributeList(1))
40 return false;
41
42 HANDLE raw_self_process_handle = self_process_handle_.Get();
43 if (!startup_info_.UpdateProcThreadAttribute(
44 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &raw_self_process_handle,
45 sizeof(raw_self_process_handle))) {
46 return false;
47 }
48
49 // Build the command line from a copy of the command line passed in.
50 base::CommandLine cmd_line(program);
51 cmd_line.AppendSwitchPath("database", crashpad_database);
52 cmd_line.AppendSwitchASCII(
53 "exception-pointers",
54 base::UintToString(reinterpret_cast<uintptr_t>(&exception_pointers_)));
55 cmd_line.AppendSwitchASCII(
56 "process", base::UintToString(
57 base::win::HandleToUint32(self_process_handle_.Get())));
58
59 std::wstring str_cmd_line = cmd_line.GetCommandLineString();
60
61 // Append the - for now abortive - thread argument manually.
62 str_cmd_line.append(L" --thread=");
63 // Store the command line string for easy use later.
64 cmd_line_.assign(str_cmd_line.begin(), str_cmd_line.end());
65
66 // Resize the vector to reserve space for the thread ID.
67 cmd_line_.resize(cmd_line_.size() + kCommandLineTailSize, '\0');
68
69 return true;
70 }
71
72 DWORD FallbackCrashHandlerLauncher::LaunchAndWaitForHandler(
73 EXCEPTION_POINTERS* exception_pointers) {
74 DCHECK(!cmd_line_.empty());
75 DCHECK_EQ('=', cmd_line_[cmd_line_.size() - kCommandLineTailSize - 1]);
76 // This program has crashed. Try and not use anything but the stack.
77
78 // Append the current thread's ID to the command line in-place.
79 wsprintf(&cmd_line_.back() - kCommandLineTailSize + 1, L"%d",
scottmg 2017/01/09 21:10:55 DCHECK that the return value <= kCommandLineTailSi
Sigurður Ásgeirsson 2017/01/09 21:30:38 Done. This is a vector here, which is already zero
80 GetCurrentThreadId());
81
82 // Copy the exception pointers to our member variable, whose address is
83 // already baked into the command line.
84 exception_pointers_ = *exception_pointers;
85
86 // Launch the pre-cooked command line.
87
88 PROCESS_INFORMATION process_info = {};
89 if (!CreateProcess(nullptr, // Application name.
90 &cmd_line_[0], // Command line.
91 nullptr, // Process attributes.
92 nullptr, // Thread attributes.
93 true, // Inherit handles.
94 0, // Creation flags.
95 nullptr, // Environment.
96 nullptr, // Current directory.
97 startup_info_.startup_info(), // Startup info.
98 &process_info)) {
99 return GetLastError();
100 }
101
102 // Wait on the fallback crash handler process. The expectation is that this
103 // will never return, as the fallback crash handler will terminate this
104 // process. For testing, and full-on belt and suspenders, cover for this
105 // returning.
106 DWORD error = WaitForSingleObject(process_info.hProcess, INFINITE);
107 if (error != WAIT_OBJECT_0) {
108 // This should never happen, barring handle abuse.
109 // TODO(siggi): Record an UMA metric here.
110 NOTREACHED();
111 error = GetLastError();
112 } else {
113 // On successful wait, return the exit code of the fallback crash handler
114 // process.
115 if (!GetExitCodeProcess(process_info.hProcess, &error)) {
116 // This should never happen, barring handle abuse.
117 NOTREACHED();
118 error = GetLastError();
119 }
120 }
121
122 // Close the handles returned from CreateProcess.
123 CloseHandle(process_info.hProcess);
124 CloseHandle(process_info.hThread);
125
126 return error;
127 }
128
129 } // namespace crash_reporter
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698