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

Side by Side Diff: third_party/crashpad/crashpad/client/crashpad_client_win.cc

Issue 2478633002: Update Crashpad to b47bf6c250c6b825dee1c5fbad9152c2c962e828 (Closed)
Patch Set: mac comment 2 Created 4 years, 1 month 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
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "client/crashpad_client.h" 15 #include "client/crashpad_client.h"
16 16
17 #include <windows.h> 17 #include <windows.h>
18 #include <stdint.h> 18 #include <stdint.h>
19 #include <string.h> 19 #include <string.h>
20 20
21 #include <memory> 21 #include <memory>
22 22
23 #include "base/atomicops.h" 23 #include "base/atomicops.h"
24 #include "base/logging.h" 24 #include "base/logging.h"
25 #include "base/macros.h"
25 #include "base/scoped_generic.h" 26 #include "base/scoped_generic.h"
26 #include "base/strings/string16.h" 27 #include "base/strings/string16.h"
27 #include "base/strings/stringprintf.h" 28 #include "base/strings/stringprintf.h"
28 #include "base/strings/utf_string_conversions.h" 29 #include "base/strings/utf_string_conversions.h"
29 #include "base/synchronization/lock.h" 30 #include "base/synchronization/lock.h"
30 #include "util/file/file_io.h" 31 #include "util/file/file_io.h"
32 #include "util/misc/random_string.h"
31 #include "util/win/address_types.h" 33 #include "util/win/address_types.h"
32 #include "util/win/command_line.h" 34 #include "util/win/command_line.h"
33 #include "util/win/critical_section_with_debug_info.h" 35 #include "util/win/critical_section_with_debug_info.h"
34 #include "util/win/get_function.h" 36 #include "util/win/get_function.h"
35 #include "util/win/handle.h" 37 #include "util/win/handle.h"
38 #include "util/win/initial_client_data.h"
36 #include "util/win/nt_internals.h" 39 #include "util/win/nt_internals.h"
37 #include "util/win/ntstatus_logging.h" 40 #include "util/win/ntstatus_logging.h"
38 #include "util/win/process_info.h" 41 #include "util/win/process_info.h"
39 #include "util/win/registration_protocol_win.h" 42 #include "util/win/registration_protocol_win.h"
40 #include "util/win/scoped_handle.h"
41 #include "util/win/scoped_process_suspend.h" 43 #include "util/win/scoped_process_suspend.h"
42 #include "util/win/termination_codes.h" 44 #include "util/win/termination_codes.h"
45 #include "util/win/xp_compat.h"
46
47 namespace crashpad {
43 48
44 namespace { 49 namespace {
45 50
46 // This handle is never closed. This is used to signal to the server that a dump 51 // This handle is never closed. This is used to signal to the server that a dump
47 // should be taken in the event of a crash. 52 // should be taken in the event of a crash.
48 HANDLE g_signal_exception = INVALID_HANDLE_VALUE; 53 HANDLE g_signal_exception = INVALID_HANDLE_VALUE;
49 54
50 // Where we store the exception information that the crash handler reads. 55 // Where we store the exception information that the crash handler reads.
51 crashpad::ExceptionInformation g_crash_exception_information; 56 ExceptionInformation g_crash_exception_information;
52 57
53 // These handles are never closed. g_signal_non_crash_dump is used to signal to 58 // These handles are never closed. g_signal_non_crash_dump is used to signal to
54 // the server to take a dump (not due to an exception), and the server will 59 // the server to take a dump (not due to an exception), and the server will
55 // signal g_non_crash_dump_done when the dump is completed. 60 // signal g_non_crash_dump_done when the dump is completed.
56 HANDLE g_signal_non_crash_dump = INVALID_HANDLE_VALUE; 61 HANDLE g_signal_non_crash_dump = INVALID_HANDLE_VALUE;
57 HANDLE g_non_crash_dump_done = INVALID_HANDLE_VALUE; 62 HANDLE g_non_crash_dump_done = INVALID_HANDLE_VALUE;
58 63
59 // Guards multiple simultaneous calls to DumpWithoutCrash(). This is leaked. 64 // Guards multiple simultaneous calls to DumpWithoutCrash(). This is leaked.
60 base::Lock* g_non_crash_dump_lock; 65 base::Lock* g_non_crash_dump_lock;
61 66
62 // Where we store a pointer to the context information when taking a non-crash 67 // Where we store a pointer to the context information when taking a non-crash
63 // dump. 68 // dump.
64 crashpad::ExceptionInformation g_non_crash_exception_information; 69 ExceptionInformation g_non_crash_exception_information;
70
71 enum class StartupState : int {
72 kNotReady = 0, // This must be value 0 because it is the initial value of a
73 // global AtomicWord.
74 kSucceeded = 1, // The CreateProcess() for the handler succeeded.
75 kFailed = 2, // The handler failed to start.
76 };
77
78 // This is a tri-state of type StartupState. It starts at 0 == kNotReady, and
79 // when the handler is known to have started successfully, or failed to start
80 // the value will be updated. The unhandled exception filter will not proceed
81 // until one of those two cases happens.
82 base::subtle::AtomicWord g_handler_startup_state;
65 83
66 // A CRITICAL_SECTION initialized with 84 // A CRITICAL_SECTION initialized with
67 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO to force it to be allocated with a 85 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO to force it to be allocated with a
68 // valid .DebugInfo field. The address of this critical section is given to the 86 // valid .DebugInfo field. The address of this critical section is given to the
69 // handler. All critical sections with debug info are linked in a doubly-linked 87 // handler. All critical sections with debug info are linked in a doubly-linked
70 // list, so this allows the handler to capture all of them. 88 // list, so this allows the handler to capture all of them.
71 CRITICAL_SECTION g_critical_section_with_debug_info; 89 CRITICAL_SECTION g_critical_section_with_debug_info;
72 90
91 void SetHandlerStartupState(StartupState state) {
92 DCHECK(state == StartupState::kSucceeded ||
93 state == StartupState::kFailed);
94 base::subtle::Acquire_Store(&g_handler_startup_state,
95 static_cast<base::subtle::AtomicWord>(state));
96 }
97
98 StartupState BlockUntilHandlerStartedOrFailed() {
99 // Wait until we know the handler has either succeeded or failed to start.
100 base::subtle::AtomicWord startup_state;
101 while (
102 (startup_state = base::subtle::Release_Load(&g_handler_startup_state)) ==
103 static_cast<int>(StartupState::kNotReady)) {
104 Sleep(1);
105 }
106
107 return static_cast<StartupState>(startup_state);
108 }
109
73 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { 110 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
111 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) {
112 // If we know for certain that the handler has failed to start, then abort
113 // here, rather than trying to signal to a handler that will never arrive,
114 // and then sleeping unnecessarily.
115 LOG(ERROR) << "crash server failed to launch, self-terminating";
116 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump);
117 return EXCEPTION_CONTINUE_SEARCH;
118 }
119
120 // Otherwise, we know the handler startup has succeeded, and we can continue.
121
74 // Tracks whether a thread has already entered UnhandledExceptionHandler. 122 // Tracks whether a thread has already entered UnhandledExceptionHandler.
75 static base::subtle::AtomicWord have_crashed; 123 static base::subtle::AtomicWord have_crashed;
76 124
77 // This is a per-process handler. While this handler is being invoked, other 125 // This is a per-process handler. While this handler is being invoked, other
78 // threads are still executing as usual, so multiple threads could enter at 126 // threads are still executing as usual, so multiple threads could enter at
79 // the same time. Because we're in a crashing state, we shouldn't be doing 127 // the same time. Because we're in a crashing state, we shouldn't be doing
80 // anything that might cause allocations, call into kernel mode, etc. So, we 128 // anything that might cause allocations, call into kernel mode, etc. So, we
81 // don't want to take a critical section here to avoid simultaneous access to 129 // don't want to take a critical section here to avoid simultaneous access to
82 // the global exception pointers in ExceptionInformation. Because the crash 130 // the global exception pointers in ExceptionInformation. Because the crash
83 // handler will record all threads, it's fine to simply have the second and 131 // handler will record all threads, it's fine to simply have the second and
84 // subsequent entrants block here. They will soon be suspended by the crash 132 // subsequent entrants block here. They will soon be suspended by the crash
85 // handler, and then the entire process will be terminated below. This means 133 // handler, and then the entire process will be terminated below. This means
86 // that we won't save the exception pointers from the second and further 134 // that we won't save the exception pointers from the second and further
87 // crashes, but contention here is very unlikely, and we'll still have a stack 135 // crashes, but contention here is very unlikely, and we'll still have a stack
88 // that's blocked at this location. 136 // that's blocked at this location.
89 if (base::subtle::Barrier_AtomicIncrement(&have_crashed, 1) > 1) { 137 if (base::subtle::Barrier_AtomicIncrement(&have_crashed, 1) > 1) {
90 SleepEx(INFINITE, false); 138 SleepEx(INFINITE, false);
91 } 139 }
92 140
93 // Otherwise, we're the first thread, so record the exception pointer and 141 // Otherwise, we're the first thread, so record the exception pointer and
94 // signal the crash handler. 142 // signal the crash handler.
95 g_crash_exception_information.thread_id = GetCurrentThreadId(); 143 g_crash_exception_information.thread_id = GetCurrentThreadId();
96 g_crash_exception_information.exception_pointers = 144 g_crash_exception_information.exception_pointers =
97 reinterpret_cast<crashpad::WinVMAddress>(exception_pointers); 145 reinterpret_cast<WinVMAddress>(exception_pointers);
98 146
99 // Now signal the crash server, which will take a dump and then terminate us 147 // Now signal the crash server, which will take a dump and then terminate us
100 // when it's complete. 148 // when it's complete.
101 SetEvent(g_signal_exception); 149 SetEvent(g_signal_exception);
102 150
103 // Time to wait for the handler to create a dump. 151 // Time to wait for the handler to create a dump.
104 const DWORD kMillisecondsUntilTerminate = 60 * 1000; 152 const DWORD kMillisecondsUntilTerminate = 60 * 1000;
105 153
106 // Sleep for a while to allow it to process us. Eventually, we terminate 154 // Sleep for a while to allow it to process us. Eventually, we terminate
107 // ourselves in case the crash server is gone, so that we don't leave zombies 155 // ourselves in case the crash server is gone, so that we don't leave zombies
108 // around. This would ideally never happen. 156 // around. This would ideally never happen.
109 Sleep(kMillisecondsUntilTerminate); 157 Sleep(kMillisecondsUntilTerminate);
110 158
111 LOG(ERROR) << "crash server did not respond, self-terminating"; 159 LOG(ERROR) << "crash server did not respond, self-terminating";
112 160
113 TerminateProcess(GetCurrentProcess(), crashpad::kTerminationCodeCrashNoDump); 161 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump);
114 162
115 return EXCEPTION_CONTINUE_SEARCH; 163 return EXCEPTION_CONTINUE_SEARCH;
116 } 164 }
117 165
118 std::wstring FormatArgumentString(const std::string& name, 166 std::wstring FormatArgumentString(const std::string& name,
119 const std::wstring& value) { 167 const std::wstring& value) {
120 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value; 168 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value;
121 } 169 }
122 170
123 struct ScopedProcThreadAttributeListTraits { 171 struct ScopedProcThreadAttributeListTraits {
124 static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() { 172 static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() { return nullptr; }
125 return nullptr;
126 }
127 173
128 static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) { 174 static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) {
129 // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION() 175 // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION()
130 // because it will only be called if InitializeProcThreadAttributeList() and 176 // because it will only be called if InitializeProcThreadAttributeList() and
131 // UpdateProcThreadAttribute() are present. 177 // UpdateProcThreadAttribute() are present.
132 static const auto delete_proc_thread_attribute_list = 178 static const auto delete_proc_thread_attribute_list =
133 GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList); 179 GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList);
134 delete_proc_thread_attribute_list(proc_thread_attribute_list); 180 delete_proc_thread_attribute_list(proc_thread_attribute_list);
135 } 181 }
136 }; 182 };
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 data_vector->push_back(static_cast<unsigned char>((data & 0xff0000) >> 16)); 225 data_vector->push_back(static_cast<unsigned char>((data & 0xff0000) >> 16));
180 data_vector->push_back(static_cast<unsigned char>((data & 0xff000000) >> 24)); 226 data_vector->push_back(static_cast<unsigned char>((data & 0xff000000) >> 24));
181 } 227 }
182 228
183 void AddUint64(std::vector<unsigned char>* data_vector, uint64_t data) { 229 void AddUint64(std::vector<unsigned char>* data_vector, uint64_t data) {
184 AddUint32(data_vector, static_cast<uint32_t>(data & 0xffffffffULL)); 230 AddUint32(data_vector, static_cast<uint32_t>(data & 0xffffffffULL));
185 AddUint32(data_vector, 231 AddUint32(data_vector,
186 static_cast<uint32_t>((data & 0xffffffff00000000ULL) >> 32)); 232 static_cast<uint32_t>((data & 0xffffffff00000000ULL) >> 32));
187 } 233 }
188 234
189 } // namespace 235 //! \brief Creates a randomized pipe name to listen for client registrations
236 //! on and returns its name.
237 //!
238 //! \param[out] pipe_name The pipe name that will be listened on.
239 //! \param[out] pipe_handle The first pipe instance corresponding for the pipe.
240 void CreatePipe(std::wstring* pipe_name, ScopedFileHANDLE* pipe_instance) {
241 int tries = 5;
242 std::string pipe_name_base =
243 base::StringPrintf("\\\\.\\pipe\\crashpad_%d_", GetCurrentProcessId());
244 do {
245 *pipe_name = base::UTF8ToUTF16(pipe_name_base + RandomString());
190 246
191 namespace crashpad { 247 pipe_instance->reset(CreateNamedPipeInstance(*pipe_name, true));
192 248
193 CrashpadClient::CrashpadClient() 249 // CreateNamedPipe() is documented as setting the error to
194 : ipc_pipe_() { 250 // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the
251 // pipe name is already in use. However it may set the error to other codes
252 // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its
253 // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already
254 // exists and its attributes differ from those specified to
255 // CreateNamedPipe()). Some of these errors may be ambiguous: for example,
256 // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called
257 // incorrectly even in the absence of an existing pipe by the same name.
258 // Rather than chasing down all of the possible errors that might indicate
259 // that a pipe name is already in use, retry up to a few times on any error.
260 } while (!pipe_instance->is_valid() && --tries);
261
262 PCHECK(pipe_instance->is_valid()) << "CreateNamedPipe";
195 } 263 }
196 264
197 CrashpadClient::~CrashpadClient() { 265 struct BackgroundHandlerStartThreadData {
198 } 266 BackgroundHandlerStartThreadData(
267 const base::FilePath& handler,
268 const base::FilePath& database,
269 const base::FilePath& metrics_dir,
270 const std::string& url,
271 const std::map<std::string, std::string>& annotations,
272 const std::vector<std::string>& arguments,
273 const std::wstring& ipc_pipe,
274 ScopedFileHANDLE ipc_pipe_handle)
275 : handler(handler),
276 database(database),
277 metrics_dir(metrics_dir),
278 url(url),
279 annotations(annotations),
280 arguments(arguments),
281 ipc_pipe(ipc_pipe),
282 ipc_pipe_handle(std::move(ipc_pipe_handle)) {}
199 283
200 bool CrashpadClient::StartHandler( 284 base::FilePath handler;
201 const base::FilePath& handler, 285 base::FilePath database;
202 const base::FilePath& database, 286 base::FilePath metrics_dir;
203 const base::FilePath& metrics_dir, 287 std::string url;
204 const std::string& url, 288 std::map<std::string, std::string> annotations;
205 const std::map<std::string, std::string>& annotations, 289 std::vector<std::string> arguments;
206 const std::vector<std::string>& arguments, 290 std::wstring ipc_pipe;
207 bool restartable) { 291 ScopedFileHANDLE ipc_pipe_handle;
208 DCHECK(ipc_pipe_.empty()); 292 };
209 293
210 HANDLE pipe_read; 294 // Ensures that SetHandlerStartupState() is called on scope exit. Assumes
211 HANDLE pipe_write; 295 // failure, and on success, SetSuccessful() should be called.
212 SECURITY_ATTRIBUTES security_attributes = {}; 296 class ScopedCallSetHandlerStartupState {
213 security_attributes.nLength = sizeof(security_attributes); 297 public:
214 security_attributes.bInheritHandle = TRUE; 298 ScopedCallSetHandlerStartupState() : successful_(false) {}
215 if (!CreatePipe(&pipe_read, &pipe_write, &security_attributes, 0)) { 299
216 PLOG(ERROR) << "CreatePipe"; 300 ~ScopedCallSetHandlerStartupState() {
217 return false; 301 SetHandlerStartupState(successful_ ? StartupState::kSucceeded
302 : StartupState::kFailed);
218 } 303 }
219 ScopedFileHandle pipe_read_owner(pipe_read);
220 ScopedFileHandle pipe_write_owner(pipe_write);
221 304
222 // The new process only needs the write side of the pipe. 305 void SetSuccessful() { successful_ = true; }
223 BOOL rv = SetHandleInformation(pipe_read, HANDLE_FLAG_INHERIT, 0); 306
224 PLOG_IF(WARNING, !rv) << "SetHandleInformation"; 307 private:
308 bool successful_;
309
310 DISALLOW_COPY_AND_ASSIGN(ScopedCallSetHandlerStartupState);
311 };
312
313 bool StartHandlerProcess(
314 std::unique_ptr<BackgroundHandlerStartThreadData> data) {
315 ScopedCallSetHandlerStartupState scoped_startup_state_caller;
225 316
226 std::wstring command_line; 317 std::wstring command_line;
227 AppendCommandLineArgument(handler.value(), &command_line); 318 AppendCommandLineArgument(data->handler.value(), &command_line);
228 for (const std::string& argument : arguments) { 319 for (const std::string& argument : data->arguments) {
229 AppendCommandLineArgument(base::UTF8ToUTF16(argument), &command_line); 320 AppendCommandLineArgument(base::UTF8ToUTF16(argument), &command_line);
230 } 321 }
231 if (!database.value().empty()) { 322 if (!data->database.value().empty()) {
232 AppendCommandLineArgument(FormatArgumentString("database",
233 database.value()),
234 &command_line);
235 }
236 if (!metrics_dir.value().empty()) {
237 AppendCommandLineArgument( 323 AppendCommandLineArgument(
238 FormatArgumentString("metrics-dir", metrics_dir.value()), 324 FormatArgumentString("database", data->database.value()),
239 &command_line); 325 &command_line);
240 } 326 }
241 if (!url.empty()) { 327 if (!data->metrics_dir.value().empty()) {
242 AppendCommandLineArgument(FormatArgumentString("url", 328 AppendCommandLineArgument(
243 base::UTF8ToUTF16(url)), 329 FormatArgumentString("metrics-dir", data->metrics_dir.value()),
244 &command_line); 330 &command_line);
245 } 331 }
246 for (const auto& kv : annotations) { 332 if (!data->url.empty()) {
333 AppendCommandLineArgument(
334 FormatArgumentString("url", base::UTF8ToUTF16(data->url)),
335 &command_line);
336 }
337 for (const auto& kv : data->annotations) {
247 AppendCommandLineArgument( 338 AppendCommandLineArgument(
248 FormatArgumentString("annotation", 339 FormatArgumentString("annotation",
249 base::UTF8ToUTF16(kv.first + '=' + kv.second)), 340 base::UTF8ToUTF16(kv.first + '=' + kv.second)),
250 &command_line); 341 &command_line);
251 } 342 }
343
344 ScopedKernelHANDLE this_process(
345 OpenProcess(kXPProcessAllAccess, true, GetCurrentProcessId()));
346 if (!this_process.is_valid()) {
347 PLOG(ERROR) << "OpenProcess";
348 return false;
349 }
350
351 InitialClientData initial_client_data(
352 g_signal_exception,
353 g_signal_non_crash_dump,
354 g_non_crash_dump_done,
355 data->ipc_pipe_handle.get(),
356 this_process.get(),
357 reinterpret_cast<WinVMAddress>(&g_crash_exception_information),
358 reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information),
359 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info));
252 AppendCommandLineArgument( 360 AppendCommandLineArgument(
253 base::UTF8ToUTF16(base::StringPrintf("--handshake-handle=0x%x", 361 base::UTF8ToUTF16(std::string("--initial-client-data=") +
254 HandleToInt(pipe_write))), 362 initial_client_data.StringRepresentation()),
255 &command_line); 363 &command_line);
256 364
365 BOOL rv;
257 DWORD creation_flags; 366 DWORD creation_flags;
258 STARTUPINFOEX startup_info = {}; 367 STARTUPINFOEX startup_info = {};
259 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; 368 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
260 startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 369 startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
261 startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 370 startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
262 startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); 371 startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
263 372
264 std::vector<HANDLE> handle_list; 373 std::vector<HANDLE> handle_list;
265 std::unique_ptr<uint8_t[]> proc_thread_attribute_list_storage; 374 std::unique_ptr<uint8_t[]> proc_thread_attribute_list_storage;
266 ScopedProcThreadAttributeList proc_thread_attribute_list_owner; 375 ScopedProcThreadAttributeList proc_thread_attribute_list_owner;
(...skipping 30 matching lines...) Expand all
297 reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>( 406 reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(
298 proc_thread_attribute_list_storage.get()); 407 proc_thread_attribute_list_storage.get());
299 rv = initialize_proc_thread_attribute_list( 408 rv = initialize_proc_thread_attribute_list(
300 startup_info.lpAttributeList, 1, 0, &size); 409 startup_info.lpAttributeList, 1, 0, &size);
301 if (!rv) { 410 if (!rv) {
302 PLOG(ERROR) << "InitializeProcThreadAttributeList"; 411 PLOG(ERROR) << "InitializeProcThreadAttributeList";
303 return false; 412 return false;
304 } 413 }
305 proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList); 414 proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList);
306 415
307 handle_list.reserve(4); 416 handle_list.reserve(8);
308 handle_list.push_back(pipe_write); 417 handle_list.push_back(g_signal_exception);
418 handle_list.push_back(g_signal_non_crash_dump);
419 handle_list.push_back(g_non_crash_dump_done);
420 handle_list.push_back(data->ipc_pipe_handle.get());
421 handle_list.push_back(this_process.get());
309 AddHandleToListIfValidAndInheritable(&handle_list, 422 AddHandleToListIfValidAndInheritable(&handle_list,
310 startup_info.StartupInfo.hStdInput); 423 startup_info.StartupInfo.hStdInput);
311 AddHandleToListIfValidAndInheritable(&handle_list, 424 AddHandleToListIfValidAndInheritable(&handle_list,
312 startup_info.StartupInfo.hStdOutput); 425 startup_info.StartupInfo.hStdOutput);
313 AddHandleToListIfValidAndInheritable(&handle_list, 426 AddHandleToListIfValidAndInheritable(&handle_list,
314 startup_info.StartupInfo.hStdError); 427 startup_info.StartupInfo.hStdError);
315 rv = update_proc_thread_attribute( 428 rv = update_proc_thread_attribute(
316 startup_info.lpAttributeList, 429 startup_info.lpAttributeList,
317 0, 430 0,
318 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, 431 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
319 &handle_list[0], 432 &handle_list[0],
320 handle_list.size() * sizeof(handle_list[0]), 433 handle_list.size() * sizeof(handle_list[0]),
321 nullptr, 434 nullptr,
322 nullptr); 435 nullptr);
323 if (!rv) { 436 if (!rv) {
324 PLOG(ERROR) << "UpdateProcThreadAttribute"; 437 PLOG(ERROR) << "UpdateProcThreadAttribute";
325 return false; 438 return false;
326 } 439 }
327 } 440 }
328 441
329 PROCESS_INFORMATION process_info; 442 PROCESS_INFORMATION process_info;
330 rv = CreateProcess(handler.value().c_str(), 443 rv = CreateProcess(data->handler.value().c_str(),
331 &command_line[0], 444 &command_line[0],
332 nullptr, 445 nullptr,
333 nullptr, 446 nullptr,
334 true, 447 true,
335 creation_flags, 448 creation_flags,
336 nullptr, 449 nullptr,
337 nullptr, 450 nullptr,
338 &startup_info.StartupInfo, 451 &startup_info.StartupInfo,
339 &process_info); 452 &process_info);
340 if (!rv) { 453 if (!rv) {
341 PLOG(ERROR) << "CreateProcess"; 454 PLOG(ERROR) << "CreateProcess";
342 return false; 455 return false;
343 } 456 }
344 457
345 rv = CloseHandle(process_info.hThread); 458 rv = CloseHandle(process_info.hThread);
346 PLOG_IF(WARNING, !rv) << "CloseHandle thread"; 459 PLOG_IF(WARNING, !rv) << "CloseHandle thread";
347 460
348 rv = CloseHandle(process_info.hProcess); 461 rv = CloseHandle(process_info.hProcess);
349 PLOG_IF(WARNING, !rv) << "CloseHandle process"; 462 PLOG_IF(WARNING, !rv) << "CloseHandle process";
350 463
351 pipe_write_owner.reset(); 464 // It is important to close our side of the pipe here before confirming that
465 // we can communicate with the server. By doing so, the only remaining copy of
466 // the server side of the pipe belongs to the exception handler process we
467 // just spawned. Otherwise, the pipe will continue to exist indefinitely, so
468 // the connection loop will not detect that it will never be serviced.
469 data->ipc_pipe_handle.reset();
352 470
353 uint32_t ipc_pipe_length; 471 // Confirm that the server is waiting for connections before continuing.
354 if (!LoggingReadFile(pipe_read, &ipc_pipe_length, sizeof(ipc_pipe_length))) { 472 ClientToServerMessage message = {};
473 message.type = ClientToServerMessage::kPing;
474 ServerToClientMessage response = {};
475 if (!SendToCrashHandlerServer(data->ipc_pipe, message, &response)) {
355 return false; 476 return false;
356 } 477 }
357 478
358 ipc_pipe_.resize(ipc_pipe_length); 479 scoped_startup_state_caller.SetSuccessful();
359 if (ipc_pipe_length && 480 return true;
360 !LoggingReadFile( 481 }
361 pipe_read, &ipc_pipe_[0], ipc_pipe_length * sizeof(ipc_pipe_[0]))) { 482
362 return false; 483 DWORD WINAPI BackgroundHandlerStartThreadProc(void* data) {
484 std::unique_ptr<BackgroundHandlerStartThreadData> data_as_ptr(
485 reinterpret_cast<BackgroundHandlerStartThreadData*>(data));
486 return StartHandlerProcess(std::move(data_as_ptr)) ? 0 : 1;
487 }
488
489 void CommonInProcessInitialization() {
490 // We create this dummy CRITICAL_SECTION with the
491 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO flag set to have an entry point
492 // into the doubly-linked list of RTL_CRITICAL_SECTION_DEBUG objects. This
493 // allows us to walk the list at crash time to gather data for !locks. A
494 // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head
495 // of the list. But that is not an exported symbol, so on an arbitrary client
496 // machine, we don't have a way of getting that pointer.
497 InitializeCriticalSectionWithDebugInfoIfPossible(
498 &g_critical_section_with_debug_info);
499
500 g_non_crash_dump_lock = new base::Lock();
501 }
502
503 } // namespace
504
505 CrashpadClient::CrashpadClient() : ipc_pipe_(), handler_start_thread_() {}
506
507 CrashpadClient::~CrashpadClient() {}
508
509 bool CrashpadClient::StartHandler(
510 const base::FilePath& handler,
511 const base::FilePath& database,
512 const base::FilePath& metrics_dir,
513 const std::string& url,
514 const std::map<std::string, std::string>& annotations,
515 const std::vector<std::string>& arguments,
516 bool restartable,
517 bool asynchronous_start) {
518 DCHECK(ipc_pipe_.empty());
519
520 // Both the pipe and the signalling events have to be created on the main
521 // thread (not the spawning thread) so that they're valid after we return from
522 // this function.
523 ScopedFileHANDLE ipc_pipe_handle;
524 CreatePipe(&ipc_pipe_, &ipc_pipe_handle);
525
526 SECURITY_ATTRIBUTES security_attributes = {0};
527 security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
528 security_attributes.bInheritHandle = true;
529
530 g_signal_exception =
531 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
532 g_signal_non_crash_dump =
533 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
534 g_non_crash_dump_done =
535 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
536
537 CommonInProcessInitialization();
538
539 SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
540
541 auto data = new BackgroundHandlerStartThreadData(handler,
542 database,
543 metrics_dir,
544 url,
545 annotations,
546 arguments,
547 ipc_pipe_,
548 std::move(ipc_pipe_handle));
549
550 if (asynchronous_start) {
551 // It is important that the current thread not be synchronized with the
552 // thread that is created here. StartHandler() needs to be callable inside a
553 // DllMain(). In that case, the background thread will not start until the
554 // current DllMain() completes, which would cause deadlock if it was waited
555 // upon.
556 handler_start_thread_.reset(CreateThread(nullptr,
557 0,
558 &BackgroundHandlerStartThreadProc,
559 reinterpret_cast<void*>(data),
560 0,
561 nullptr));
562 if (!handler_start_thread_.is_valid()) {
563 PLOG(ERROR) << "CreateThread";
564 SetHandlerStartupState(StartupState::kFailed);
565 return false;
566 }
567
568 // In asynchronous mode, we can't report on the overall success or failure
569 // of initialization at this point.
570 return true;
571 } else {
572 return StartHandlerProcess(
573 std::unique_ptr<BackgroundHandlerStartThreadData>(data));
363 } 574 }
364
365 return true;
366 } 575 }
367 576
368 bool CrashpadClient::SetHandlerIPCPipe(const std::wstring& ipc_pipe) { 577 bool CrashpadClient::SetHandlerIPCPipe(const std::wstring& ipc_pipe) {
369 DCHECK(ipc_pipe_.empty()); 578 DCHECK(ipc_pipe_.empty());
370 DCHECK(!ipc_pipe.empty()); 579 DCHECK(!ipc_pipe.empty());
371 580
372 ipc_pipe_ = ipc_pipe; 581 ipc_pipe_ = ipc_pipe;
373 582
374 return true;
375 }
376
377 std::wstring CrashpadClient::GetHandlerIPCPipe() const {
378 DCHECK(!ipc_pipe_.empty());
379 return ipc_pipe_;
380 }
381
382 bool CrashpadClient::UseHandler() {
383 DCHECK(!ipc_pipe_.empty()); 583 DCHECK(!ipc_pipe_.empty());
384 DCHECK_EQ(g_signal_exception, INVALID_HANDLE_VALUE); 584 DCHECK_EQ(g_signal_exception, INVALID_HANDLE_VALUE);
385 DCHECK_EQ(g_signal_non_crash_dump, INVALID_HANDLE_VALUE); 585 DCHECK_EQ(g_signal_non_crash_dump, INVALID_HANDLE_VALUE);
386 DCHECK_EQ(g_non_crash_dump_done, INVALID_HANDLE_VALUE); 586 DCHECK_EQ(g_non_crash_dump_done, INVALID_HANDLE_VALUE);
387 DCHECK(!g_critical_section_with_debug_info.DebugInfo); 587 DCHECK(!g_critical_section_with_debug_info.DebugInfo);
388 DCHECK(!g_non_crash_dump_lock); 588 DCHECK(!g_non_crash_dump_lock);
389 589
390 ClientToServerMessage message; 590 ClientToServerMessage message;
391 memset(&message, 0, sizeof(message)); 591 memset(&message, 0, sizeof(message));
392 message.type = ClientToServerMessage::kRegister; 592 message.type = ClientToServerMessage::kRegister;
393 message.registration.version = RegistrationRequest::kMessageVersion; 593 message.registration.version = RegistrationRequest::kMessageVersion;
394 message.registration.client_process_id = GetCurrentProcessId(); 594 message.registration.client_process_id = GetCurrentProcessId();
395 message.registration.crash_exception_information = 595 message.registration.crash_exception_information =
396 reinterpret_cast<WinVMAddress>(&g_crash_exception_information); 596 reinterpret_cast<WinVMAddress>(&g_crash_exception_information);
397 message.registration.non_crash_exception_information = 597 message.registration.non_crash_exception_information =
398 reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information); 598 reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information);
399 599
400 // We create this dummy CRITICAL_SECTION with the 600 CommonInProcessInitialization();
401 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO flag set to have an entry point 601
402 // into the doubly-linked list of RTL_CRITICAL_SECTION_DEBUG objects. This 602 message.registration.critical_section_address =
403 // allows us to walk the list at crash time to gather data for !locks. A 603 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info);
404 // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head
405 // of the list. But that is not an exported symbol, so on an arbitrary client
406 // machine, we don't have a way of getting that pointer.
407 if (InitializeCriticalSectionWithDebugInfoIfPossible(
408 &g_critical_section_with_debug_info)) {
409 message.registration.critical_section_address =
410 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info);
411 }
412 604
413 ServerToClientMessage response = {}; 605 ServerToClientMessage response = {};
414 606
415 if (!SendToCrashHandlerServer(ipc_pipe_, message, &response)) { 607 if (!SendToCrashHandlerServer(ipc_pipe_, message, &response)) {
416 return false; 608 return false;
417 } 609 }
418 610
611 SetHandlerStartupState(StartupState::kSucceeded);
612 SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
613
419 // The server returns these already duplicated to be valid in this process. 614 // The server returns these already duplicated to be valid in this process.
420 g_signal_exception = 615 g_signal_exception =
421 IntToHandle(response.registration.request_crash_dump_event); 616 IntToHandle(response.registration.request_crash_dump_event);
422 g_signal_non_crash_dump = 617 g_signal_non_crash_dump =
423 IntToHandle(response.registration.request_non_crash_dump_event); 618 IntToHandle(response.registration.request_non_crash_dump_event);
424 g_non_crash_dump_done = 619 g_non_crash_dump_done =
425 IntToHandle(response.registration.non_crash_dump_completed_event); 620 IntToHandle(response.registration.non_crash_dump_completed_event);
426 621
427 g_non_crash_dump_lock = new base::Lock(); 622 return true;
623 }
428 624
429 // In theory we could store the previous handler but it is not clear what 625 std::wstring CrashpadClient::GetHandlerIPCPipe() const {
430 // use we have for it. 626 DCHECK(!ipc_pipe_.empty());
431 SetUnhandledExceptionFilter(&UnhandledExceptionHandler); 627 return ipc_pipe_;
432 return true; 628 }
629
630 bool CrashpadClient::WaitForHandlerStart() {
631 DCHECK(handler_start_thread_.is_valid());
632 if (WaitForSingleObject(handler_start_thread_.get(), INFINITE) !=
633 WAIT_OBJECT_0) {
634 PLOG(ERROR) << "WaitForSingleObject";
635 return false;
636 }
637
638 DWORD exit_code;
639 if (!GetExitCodeThread(handler_start_thread_.get(), &exit_code)) {
640 PLOG(ERROR) << "GetExitCodeThread";
641 return false;
642 }
643
644 handler_start_thread_.reset();
645 return exit_code == 0;
433 } 646 }
434 647
435 // static 648 // static
436 void CrashpadClient::DumpWithoutCrash(const CONTEXT& context) { 649 void CrashpadClient::DumpWithoutCrash(const CONTEXT& context) {
437 if (g_signal_non_crash_dump == INVALID_HANDLE_VALUE || 650 if (g_signal_non_crash_dump == INVALID_HANDLE_VALUE ||
438 g_non_crash_dump_done == INVALID_HANDLE_VALUE) { 651 g_non_crash_dump_done == INVALID_HANDLE_VALUE) {
439 LOG(ERROR) << "haven't called UseHandler()"; 652 LOG(ERROR) << "not connected";
440 return; 653 return;
441 } 654 }
442 655
656 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) {
657 // If we know for certain that the handler has failed to start, then abort
658 // here, as we would otherwise wait indefinitely for the
659 // g_non_crash_dump_done event that would never be signalled.
660 LOG(ERROR) << "crash server failed to launch, no dump captured";
661 return;
662 }
663
443 // In the non-crashing case, we aren't concerned about avoiding calls into 664 // In the non-crashing case, we aren't concerned about avoiding calls into
444 // Win32 APIs, so just use regular locking here in case of multiple threads 665 // Win32 APIs, so just use regular locking here in case of multiple threads
445 // calling this function. If a crash occurs while we're in here, the worst 666 // calling this function. If a crash occurs while we're in here, the worst
446 // that can happen is that the server captures a partial dump for this path 667 // that can happen is that the server captures a partial dump for this path
447 // because on the other thread gathering a crash dump, it TerminateProcess()d, 668 // because on the other thread gathering a crash dump, it TerminateProcess()d,
448 // causing this one to abort. 669 // causing this one to abort.
449 base::AutoLock lock(*g_non_crash_dump_lock); 670 base::AutoLock lock(*g_non_crash_dump_lock);
450 671
451 // Create a fake EXCEPTION_POINTERS to give the handler something to work 672 // Create a fake EXCEPTION_POINTERS to give the handler something to work
452 // with. 673 // with.
(...skipping 15 matching lines...) Expand all
468 #if defined(ARCH_CPU_64_BITS) 689 #if defined(ARCH_CPU_64_BITS)
469 record.ExceptionAddress = reinterpret_cast<void*>(context.Rip); 690 record.ExceptionAddress = reinterpret_cast<void*>(context.Rip);
470 #else 691 #else
471 record.ExceptionAddress = reinterpret_cast<void*>(context.Eip); 692 record.ExceptionAddress = reinterpret_cast<void*>(context.Eip);
472 #endif // ARCH_CPU_64_BITS 693 #endif // ARCH_CPU_64_BITS
473 694
474 exception_pointers.ExceptionRecord = &record; 695 exception_pointers.ExceptionRecord = &record;
475 696
476 g_non_crash_exception_information.thread_id = GetCurrentThreadId(); 697 g_non_crash_exception_information.thread_id = GetCurrentThreadId();
477 g_non_crash_exception_information.exception_pointers = 698 g_non_crash_exception_information.exception_pointers =
478 reinterpret_cast<crashpad::WinVMAddress>(&exception_pointers); 699 reinterpret_cast<WinVMAddress>(&exception_pointers);
479 700
480 bool set_event_result = !!SetEvent(g_signal_non_crash_dump); 701 bool set_event_result = !!SetEvent(g_signal_non_crash_dump);
481 PLOG_IF(ERROR, !set_event_result) << "SetEvent"; 702 PLOG_IF(ERROR, !set_event_result) << "SetEvent";
482 703
483 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); 704 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE);
484 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; 705 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject";
485 } 706 }
486 707
487 // static 708 // static
488 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) { 709 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) {
489 if (g_signal_exception == INVALID_HANDLE_VALUE) { 710 if (g_signal_exception == INVALID_HANDLE_VALUE) {
490 LOG(ERROR) << "haven't called UseHandler(), no dump captured"; 711 LOG(ERROR) << "not connected";
491 TerminateProcess(GetCurrentProcess(), kTerminationCodeUseHandlerNotCalled); 712 TerminateProcess(GetCurrentProcess(),
713 kTerminationCodeNotConnectedToHandler);
492 return; 714 return;
493 } 715 }
494 716
717 // We don't need to check for handler startup here, as
718 // UnhandledExceptionHandler() necessarily does that.
719
495 UnhandledExceptionHandler(exception_pointers); 720 UnhandledExceptionHandler(exception_pointers);
496 } 721 }
497 722
498 bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process, 723 bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process,
499 HANDLE blame_thread, 724 HANDLE blame_thread,
500 DWORD exception_code) const { 725 DWORD exception_code) const {
501 // Confirm we're on Vista or later. 726 // Confirm we're on Vista or later.
502 const DWORD version = GetVersion(); 727 const DWORD version = GetVersion();
503 const DWORD major_version = LOBYTE(LOWORD(version)); 728 const DWORD major_version = LOBYTE(LOWORD(version));
504 if (major_version < 6) { 729 if (major_version < 6) {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 status = NtClose(injected_thread); 957 status = NtClose(injected_thread);
733 if (!NT_SUCCESS(status)) { 958 if (!NT_SUCCESS(status)) {
734 NTSTATUS_LOG(ERROR, status) << "NtClose"; 959 NTSTATUS_LOG(ERROR, status) << "NtClose";
735 result = false; 960 result = false;
736 } 961 }
737 962
738 return result; 963 return result;
739 } 964 }
740 965
741 } // namespace crashpad 966 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698