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

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

Issue 2555353002: Update Crashpad to 32981a3ee9d7c2769fb27afa038fe2e194cfa329 (Closed)
Patch Set: fix readme Created 4 years 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 <signal.h>
18 #include <stdint.h> 19 #include <stdint.h>
19 #include <string.h> 20 #include <string.h>
20 21
21 #include <memory> 22 #include <memory>
22 23
23 #include "base/atomicops.h" 24 #include "base/atomicops.h"
24 #include "base/logging.h" 25 #include "base/logging.h"
25 #include "base/macros.h" 26 #include "base/macros.h"
26 #include "base/scoped_generic.h" 27 #include "base/scoped_generic.h"
27 #include "base/strings/string16.h" 28 #include "base/strings/string16.h"
28 #include "base/strings/stringprintf.h" 29 #include "base/strings/stringprintf.h"
29 #include "base/strings/utf_string_conversions.h" 30 #include "base/strings/utf_string_conversions.h"
30 #include "base/synchronization/lock.h" 31 #include "base/synchronization/lock.h"
31 #include "util/file/file_io.h" 32 #include "util/file/file_io.h"
32 #include "util/misc/random_string.h" 33 #include "util/misc/random_string.h"
33 #include "util/win/address_types.h" 34 #include "util/win/address_types.h"
35 #include "util/win/capture_context.h"
34 #include "util/win/command_line.h" 36 #include "util/win/command_line.h"
35 #include "util/win/critical_section_with_debug_info.h" 37 #include "util/win/critical_section_with_debug_info.h"
36 #include "util/win/get_function.h" 38 #include "util/win/get_function.h"
37 #include "util/win/handle.h" 39 #include "util/win/handle.h"
38 #include "util/win/initial_client_data.h" 40 #include "util/win/initial_client_data.h"
39 #include "util/win/nt_internals.h" 41 #include "util/win/nt_internals.h"
40 #include "util/win/ntstatus_logging.h" 42 #include "util/win/ntstatus_logging.h"
41 #include "util/win/process_info.h" 43 #include "util/win/process_info.h"
42 #include "util/win/registration_protocol_win.h" 44 #include "util/win/registration_protocol_win.h"
43 #include "util/win/scoped_process_suspend.h" 45 #include "util/win/scoped_process_suspend.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 while ( 103 while (
102 (startup_state = base::subtle::Release_Load(&g_handler_startup_state)) == 104 (startup_state = base::subtle::Release_Load(&g_handler_startup_state)) ==
103 static_cast<int>(StartupState::kNotReady)) { 105 static_cast<int>(StartupState::kNotReady)) {
104 Sleep(1); 106 Sleep(1);
105 } 107 }
106 108
107 return static_cast<StartupState>(startup_state); 109 return static_cast<StartupState>(startup_state);
108 } 110 }
109 111
110 #if defined(ADDRESS_SANITIZER) 112 #if defined(ADDRESS_SANITIZER)
111 extern "C" LONG 113 extern "C" LONG __asan_unhandled_exception_filter(EXCEPTION_POINTERS* info);
112 __asan_unhandled_exception_filter(EXCEPTION_POINTERS* info);
113 #endif 114 #endif
114 115
115 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { 116 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
117 #if defined(ADDRESS_SANITIZER)
116 // In ASan builds, delegate to the ASan exception filter. 118 // In ASan builds, delegate to the ASan exception filter.
117 #if defined(ADDRESS_SANITIZER)
118 LONG status = __asan_unhandled_exception_filter(exception_pointers); 119 LONG status = __asan_unhandled_exception_filter(exception_pointers);
119 if (status != EXCEPTION_CONTINUE_SEARCH) 120 if (status != EXCEPTION_CONTINUE_SEARCH)
120 return status; 121 return status;
121 #endif 122 #endif
122 123
123 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) { 124 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) {
124 // If we know for certain that the handler has failed to start, then abort 125 // If we know for certain that the handler has failed to start, then abort
125 // here, rather than trying to signal to a handler that will never arrive, 126 // here, rather than trying to signal to a handler that will never arrive,
126 // and then sleeping unnecessarily. 127 // and then sleeping unnecessarily.
127 LOG(ERROR) << "crash server failed to launch, self-terminating"; 128 LOG(ERROR) << "crash server failed to launch, self-terminating";
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 // around. This would ideally never happen. 169 // around. This would ideally never happen.
169 Sleep(kMillisecondsUntilTerminate); 170 Sleep(kMillisecondsUntilTerminate);
170 171
171 LOG(ERROR) << "crash server did not respond, self-terminating"; 172 LOG(ERROR) << "crash server did not respond, self-terminating";
172 173
173 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump); 174 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump);
174 175
175 return EXCEPTION_CONTINUE_SEARCH; 176 return EXCEPTION_CONTINUE_SEARCH;
176 } 177 }
177 178
179 void HandleAbortSignal(int signum) {
180 DCHECK_EQ(signum, SIGABRT);
181
182 CONTEXT context;
183 CaptureContext(&context);
184
185 EXCEPTION_RECORD record = {};
186 record.ExceptionCode = STATUS_FATAL_APP_EXIT;
187 record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
188 #if defined(ARCH_CPU_64_BITS)
189 record.ExceptionAddress = reinterpret_cast<void*>(context.Rip);
190 #else
191 record.ExceptionAddress = reinterpret_cast<void*>(context.Eip);
192 #endif // ARCH_CPU_64_BITS
193
194 EXCEPTION_POINTERS exception_pointers;
195 exception_pointers.ContextRecord = &context;
196 exception_pointers.ExceptionRecord = &record;
197
198 UnhandledExceptionHandler(&exception_pointers);
199 }
200
178 std::wstring FormatArgumentString(const std::string& name, 201 std::wstring FormatArgumentString(const std::string& name,
179 const std::wstring& value) { 202 const std::wstring& value) {
180 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value; 203 return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value;
181 } 204 }
182 205
183 struct ScopedProcThreadAttributeListTraits { 206 struct ScopedProcThreadAttributeListTraits {
184 static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() { return nullptr; } 207 static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() { return nullptr; }
185 208
186 static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) { 209 static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) {
187 // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION() 210 // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION()
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 // allows us to walk the list at crash time to gather data for !locks. A 528 // allows us to walk the list at crash time to gather data for !locks. A
506 // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head 529 // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head
507 // of the list. But that is not an exported symbol, so on an arbitrary client 530 // of the list. But that is not an exported symbol, so on an arbitrary client
508 // machine, we don't have a way of getting that pointer. 531 // machine, we don't have a way of getting that pointer.
509 InitializeCriticalSectionWithDebugInfoIfPossible( 532 InitializeCriticalSectionWithDebugInfoIfPossible(
510 &g_critical_section_with_debug_info); 533 &g_critical_section_with_debug_info);
511 534
512 g_non_crash_dump_lock = new base::Lock(); 535 g_non_crash_dump_lock = new base::Lock();
513 } 536 }
514 537
538 void RegisterHandlers() {
539 SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
540
541 // The Windows CRT's signal.h lists:
542 // - SIGINT
543 // - SIGILL
544 // - SIGFPE
545 // - SIGSEGV
546 // - SIGTERM
547 // - SIGBREAK
548 // - SIGABRT
549 // SIGILL and SIGTERM are documented as not being generated. SIGBREAK and
550 // SIGINT are for Ctrl-Break and Ctrl-C, and aren't something for which
551 // capturing a dump is warranted. SIGFPE and SIGSEGV are captured as regular
552 // exceptions through the unhandled exception filter. This leaves SIGABRT. In
553 // the standard CRT, abort() is implemented as a synchronous call to the
554 // SIGABRT signal handler if installed, but after doing so, the unhandled
555 // exception filter is not triggered (it instead __fastfail()s). So, register
556 // to handle SIGABRT to catch abort() calls, as client code might use this and
557 // expect it to cause a crash dump. This will only work when the abort()
558 // that's called in client code is the same (or has the same behavior) as the
559 // one in use here.
560 void (*rv)(int) = signal(SIGABRT, HandleAbortSignal);
561 DCHECK_NE(rv, SIG_ERR);
562 }
563
515 } // namespace 564 } // namespace
516 565
517 CrashpadClient::CrashpadClient() : ipc_pipe_(), handler_start_thread_() {} 566 CrashpadClient::CrashpadClient() : ipc_pipe_(), handler_start_thread_() {}
518 567
519 CrashpadClient::~CrashpadClient() {} 568 CrashpadClient::~CrashpadClient() {}
520 569
521 bool CrashpadClient::StartHandler( 570 bool CrashpadClient::StartHandler(
522 const base::FilePath& handler, 571 const base::FilePath& handler,
523 const base::FilePath& database, 572 const base::FilePath& database,
524 const base::FilePath& metrics_dir, 573 const base::FilePath& metrics_dir,
(...skipping 16 matching lines...) Expand all
541 590
542 g_signal_exception = 591 g_signal_exception =
543 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr); 592 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
544 g_signal_non_crash_dump = 593 g_signal_non_crash_dump =
545 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr); 594 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
546 g_non_crash_dump_done = 595 g_non_crash_dump_done =
547 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr); 596 CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
548 597
549 CommonInProcessInitialization(); 598 CommonInProcessInitialization();
550 599
551 SetUnhandledExceptionFilter(&UnhandledExceptionHandler); 600 RegisterHandlers();
552 601
553 auto data = new BackgroundHandlerStartThreadData(handler, 602 auto data = new BackgroundHandlerStartThreadData(handler,
554 database, 603 database,
555 metrics_dir, 604 metrics_dir,
556 url, 605 url,
557 annotations, 606 annotations,
558 arguments, 607 arguments,
559 ipc_pipe_, 608 ipc_pipe_,
560 std::move(ipc_pipe_handle)); 609 std::move(ipc_pipe_handle));
561 610
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 message.registration.critical_section_address = 663 message.registration.critical_section_address =
615 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info); 664 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info);
616 665
617 ServerToClientMessage response = {}; 666 ServerToClientMessage response = {};
618 667
619 if (!SendToCrashHandlerServer(ipc_pipe_, message, &response)) { 668 if (!SendToCrashHandlerServer(ipc_pipe_, message, &response)) {
620 return false; 669 return false;
621 } 670 }
622 671
623 SetHandlerStartupState(StartupState::kSucceeded); 672 SetHandlerStartupState(StartupState::kSucceeded);
624 SetUnhandledExceptionFilter(&UnhandledExceptionHandler); 673
674 RegisterHandlers();
625 675
626 // The server returns these already duplicated to be valid in this process. 676 // The server returns these already duplicated to be valid in this process.
627 g_signal_exception = 677 g_signal_exception =
628 IntToHandle(response.registration.request_crash_dump_event); 678 IntToHandle(response.registration.request_crash_dump_event);
629 g_signal_non_crash_dump = 679 g_signal_non_crash_dump =
630 IntToHandle(response.registration.request_non_crash_dump_event); 680 IntToHandle(response.registration.request_non_crash_dump_event);
631 g_non_crash_dump_done = 681 g_non_crash_dump_done =
632 IntToHandle(response.registration.non_crash_dump_completed_event); 682 IntToHandle(response.registration.non_crash_dump_completed_event);
633 683
634 return true; 684 return true;
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
969 status = NtClose(injected_thread); 1019 status = NtClose(injected_thread);
970 if (!NT_SUCCESS(status)) { 1020 if (!NT_SUCCESS(status)) {
971 NTSTATUS_LOG(ERROR, status) << "NtClose"; 1021 NTSTATUS_LOG(ERROR, status) << "NtClose";
972 result = false; 1022 result = false;
973 } 1023 }
974 1024
975 return result; 1025 return result;
976 } 1026 }
977 1027
978 } // namespace crashpad 1028 } // namespace crashpad
OLDNEW
« no previous file with comments | « third_party/crashpad/crashpad/client/crashpad_client.h ('k') | third_party/crashpad/crashpad/client/crashpad_info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698