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

Side by Side Diff: client/crashpad_client_win.cc

Issue 1392093003: win: Capture some CRITICAL_SECTION debugging data (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: . Created 5 years, 2 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
« no previous file with comments | « no previous file | handler/win/crash_report_exception_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
(...skipping 30 matching lines...) Expand all
41 HANDLE g_signal_non_crash_dump = INVALID_HANDLE_VALUE; 41 HANDLE g_signal_non_crash_dump = INVALID_HANDLE_VALUE;
42 HANDLE g_non_crash_dump_done = INVALID_HANDLE_VALUE; 42 HANDLE g_non_crash_dump_done = INVALID_HANDLE_VALUE;
43 43
44 // Guards multiple simultaneous calls to DumpWithoutCrash(). This is leaked. 44 // Guards multiple simultaneous calls to DumpWithoutCrash(). This is leaked.
45 base::Lock* g_non_crash_dump_lock; 45 base::Lock* g_non_crash_dump_lock;
46 46
47 // Where we store a pointer to the context information when taking a non-crash 47 // Where we store a pointer to the context information when taking a non-crash
48 // dump. 48 // dump.
49 crashpad::ExceptionInformation g_non_crash_exception_information; 49 crashpad::ExceptionInformation g_non_crash_exception_information;
50 50
51 // A CRITICAL_SECTION initialized with
52 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO to force it to be allocated with a
53 // valid .DebugInfo field. The address of this critical section is given to the
54 // handler. All critical sections with debug info are linked in a doubly-linked
55 // list, so this allows the handler to capture all of them.
56 CRITICAL_SECTION g_critical_section_with_debug_info;
57
51 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { 58 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
52 // Tracks whether a thread has already entered UnhandledExceptionHandler. 59 // Tracks whether a thread has already entered UnhandledExceptionHandler.
53 static base::subtle::AtomicWord have_crashed; 60 static base::subtle::AtomicWord have_crashed;
54 61
55 // This is a per-process handler. While this handler is being invoked, other 62 // This is a per-process handler. While this handler is being invoked, other
56 // threads are still executing as usual, so multiple threads could enter at 63 // threads are still executing as usual, so multiple threads could enter at
57 // the same time. Because we're in a crashing state, we shouldn't be doing 64 // the same time. Because we're in a crashing state, we shouldn't be doing
58 // anything that might cause allocations, call into kernel mode, etc. So, we 65 // anything that might cause allocations, call into kernel mode, etc. So, we
59 // don't want to take a critical section here to avoid simultaneous access to 66 // don't want to take a critical section here to avoid simultaneous access to
60 // the global exception pointers in ExceptionInformation. Because the crash 67 // the global exception pointers in ExceptionInformation. Because the crash
(...skipping 26 matching lines...) Expand all
87 Sleep(kMillisecondsUntilTerminate); 94 Sleep(kMillisecondsUntilTerminate);
88 95
89 LOG(ERROR) << "crash server did not respond, self-terminating"; 96 LOG(ERROR) << "crash server did not respond, self-terminating";
90 97
91 const UINT kCrashExitCodeNoDump = 0xffff7001; 98 const UINT kCrashExitCodeNoDump = 0xffff7001;
92 TerminateProcess(GetCurrentProcess(), kCrashExitCodeNoDump); 99 TerminateProcess(GetCurrentProcess(), kCrashExitCodeNoDump);
93 100
94 return EXCEPTION_CONTINUE_SEARCH; 101 return EXCEPTION_CONTINUE_SEARCH;
95 } 102 }
96 103
104 BOOL CrashpadInitializeCriticalSectionEx(
105 CRITICAL_SECTION* critical_section,
106 DWORD spin_count,
107 DWORD flags) {
108 static decltype(InitializeCriticalSectionEx)* initialize_critical_section_ex =
109 reinterpret_cast<decltype(InitializeCriticalSectionEx)*>(GetProcAddress(
110 LoadLibrary(L"kernel32.dll"), "InitializeCriticalSectionEx"));
111 if (!initialize_critical_section_ex)
112 return false;
113 return initialize_critical_section_ex(critical_section, spin_count, flags);
114 }
115
97 } // namespace 116 } // namespace
98 117
99 namespace crashpad { 118 namespace crashpad {
100 119
101 CrashpadClient::CrashpadClient() { 120 CrashpadClient::CrashpadClient() {
102 } 121 }
103 122
104 CrashpadClient::~CrashpadClient() { 123 CrashpadClient::~CrashpadClient() {
105 } 124 }
106 125
107 bool CrashpadClient::StartHandler( 126 bool CrashpadClient::StartHandler(
108 const base::FilePath& handler, 127 const base::FilePath& handler,
109 const base::FilePath& database, 128 const base::FilePath& database,
110 const std::string& url, 129 const std::string& url,
111 const std::map<std::string, std::string>& annotations, 130 const std::map<std::string, std::string>& annotations,
112 const std::vector<std::string>& arguments) { 131 const std::vector<std::string>& arguments) {
113 LOG(FATAL) << "SetHandler should be used on Windows"; 132 LOG(FATAL) << "SetHandler should be used on Windows";
114 return false; 133 return false;
115 } 134 }
116 135
117 bool CrashpadClient::SetHandler(const std::string& ipc_port) { 136 bool CrashpadClient::SetHandler(const std::string& ipc_port) {
118 DCHECK_EQ(g_signal_exception, INVALID_HANDLE_VALUE); 137 DCHECK_EQ(g_signal_exception, INVALID_HANDLE_VALUE);
119 DCHECK_EQ(g_signal_non_crash_dump, INVALID_HANDLE_VALUE); 138 DCHECK_EQ(g_signal_non_crash_dump, INVALID_HANDLE_VALUE);
120 DCHECK_EQ(g_non_crash_dump_done, INVALID_HANDLE_VALUE); 139 DCHECK_EQ(g_non_crash_dump_done, INVALID_HANDLE_VALUE);
140 DCHECK(!g_critical_section_with_debug_info.DebugInfo);
121 141
122 ClientToServerMessage message; 142 ClientToServerMessage message;
123 memset(&message, 0, sizeof(message)); 143 memset(&message, 0, sizeof(message));
124 message.type = ClientToServerMessage::kRegister; 144 message.type = ClientToServerMessage::kRegister;
125 message.registration.version = RegistrationRequest::kMessageVersion; 145 message.registration.version = RegistrationRequest::kMessageVersion;
126 message.registration.client_process_id = GetCurrentProcessId(); 146 message.registration.client_process_id = GetCurrentProcessId();
127 message.registration.crash_exception_information = 147 message.registration.crash_exception_information =
128 reinterpret_cast<WinVMAddress>(&g_crash_exception_information); 148 reinterpret_cast<WinVMAddress>(&g_crash_exception_information);
129 message.registration.non_crash_exception_information = 149 message.registration.non_crash_exception_information =
130 reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information); 150 reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information);
131 151
152 // We create this dummy CRITICAL_SECTION with the
153 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO flag set to have an entry point
154 // into the doubly-linked list of RTL_CRITICAL_SECTION_DEBUG objects. This
155 // allows us to walk the list at crash time to gather data for !locks. A
156 // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head
157 // of the list. But that is not an exported symbol, so on an arbitrary client
158 // machine, we don't have a way of getting that pointer.
159 if (CrashpadInitializeCriticalSectionEx(
160 &g_critical_section_with_debug_info,
161 0,
162 RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO)) {
163 message.registration.critical_section_address =
164 reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info);
165 } else {
166 PLOG(ERROR) << "InitializeCriticalSectionEx";
167 }
168
132 ServerToClientMessage response = {0}; 169 ServerToClientMessage response = {0};
133 170
134 if (!SendToCrashHandlerServer( 171 if (!SendToCrashHandlerServer(
135 base::UTF8ToUTF16(ipc_port), message, &response)) { 172 base::UTF8ToUTF16(ipc_port), message, &response)) {
136 return false; 173 return false;
137 } 174 }
138 175
139 // The server returns these already duplicated to be valid in this process. 176 // The server returns these already duplicated to be valid in this process.
140 g_signal_exception = reinterpret_cast<HANDLE>( 177 g_signal_exception = reinterpret_cast<HANDLE>(
141 static_cast<uintptr_t>(response.registration.request_crash_dump_event)); 178 static_cast<uintptr_t>(response.registration.request_crash_dump_event));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 reinterpret_cast<crashpad::WinVMAddress>(&exception_pointers); 245 reinterpret_cast<crashpad::WinVMAddress>(&exception_pointers);
209 246
210 bool set_event_result = SetEvent(g_signal_non_crash_dump); 247 bool set_event_result = SetEvent(g_signal_non_crash_dump);
211 PLOG_IF(ERROR, !set_event_result) << "SetEvent"; 248 PLOG_IF(ERROR, !set_event_result) << "SetEvent";
212 249
213 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); 250 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE);
214 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; 251 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject";
215 } 252 }
216 253
217 } // namespace crashpad 254 } // namespace crashpad
OLDNEW
« no previous file with comments | « no previous file | handler/win/crash_report_exception_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698