Chromium Code Reviews| Index: client/crashpad_client_win.cc |
| diff --git a/client/crashpad_client_win.cc b/client/crashpad_client_win.cc |
| index 195916004198e2a517ff7b8fe30aa4f244552da9..01292b5411896e91ca3c34e44cbbe40608c5304d 100644 |
| --- a/client/crashpad_client_win.cc |
| +++ b/client/crashpad_client_win.cc |
| @@ -48,6 +48,13 @@ base::Lock* g_non_crash_dump_lock; |
| // dump. |
| crashpad::ExceptionInformation g_non_crash_exception_information; |
| +// A `CRITICAL_SECTION` initialized with |
|
Mark Mentovai
2015/10/15 00:14:56
// (as opposed to //!) comments aren’t Doxygenated
scottmg
2015/10/15 18:22:23
Done.
|
| +// `RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO` to force it to be allocated with |
| +// a valid .DebugInfo field. The address of this critical section is given to |
| +// the handler. All critical sections with debug info are linked in a |
| +// doubly-linked list, so this allows the handler to capture all of them. |
| +CRITICAL_SECTION g_critical_section_with_debug_info; |
| + |
| LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { |
| // Tracks whether a thread has already entered UnhandledExceptionHandler. |
| static base::subtle::AtomicWord have_crashed; |
| @@ -94,6 +101,18 @@ LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { |
| return EXCEPTION_CONTINUE_SEARCH; |
| } |
| +BOOL CrashpadInitializeCriticalSectionEx( |
| + CRITICAL_SECTION* critical_section, |
| + DWORD spin_count, |
| + DWORD flags) { |
| + static decltype(InitializeCriticalSectionEx)* initialize_critical_section_ex = |
| + reinterpret_cast<decltype(InitializeCriticalSectionEx)*>(GetProcAddress( |
| + LoadLibrary(L"kernel32.dll"), "InitializeCriticalSectionEx")); |
| + if (!initialize_critical_section_ex) |
| + return false; |
| + return initialize_critical_section_ex(critical_section, spin_count, flags); |
| +} |
| + |
| } // namespace |
| namespace crashpad { |
| @@ -129,6 +148,21 @@ bool CrashpadClient::SetHandler(const std::string& ipc_port) { |
| message.registration.non_crash_exception_information = |
| reinterpret_cast<WinVMAddress>(&g_non_crash_exception_information); |
| + // We create this dummy CRITICAL_SECTION with the |
| + // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO flag set to have an entry point |
| + // into the doubly-linked list of RTL_CRITICAL_SECTION_DEBUG objects. This |
| + // allows us to walk the list at crash time to gather data for !locks. A |
| + // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head |
| + // of the list. But that is not an exported symbol, so on an arbitrary client |
| + // machine, we don't have a way of getting that pointer. |
| + if (CrashpadInitializeCriticalSectionEx( |
|
Mark Mentovai
2015/10/15 00:14:56
Otherwise, PLOG().
scottmg
2015/10/15 18:22:23
Done.
|
| + &g_critical_section_with_debug_info, |
| + 0, |
| + RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO)) { |
| + message.registration.critical_section_address = |
| + reinterpret_cast<WinVMAddress>(&g_critical_section_with_debug_info); |
| + } |
| + |
| ServerToClientMessage response = {0}; |
| if (!SendToCrashHandlerServer( |