| OLD | NEW |
| 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 24 matching lines...) Expand all Loading... |
| 35 #include "util/win/capture_context.h" | 35 #include "util/win/capture_context.h" |
| 36 #include "util/win/command_line.h" | 36 #include "util/win/command_line.h" |
| 37 #include "util/win/critical_section_with_debug_info.h" | 37 #include "util/win/critical_section_with_debug_info.h" |
| 38 #include "util/win/get_function.h" | 38 #include "util/win/get_function.h" |
| 39 #include "util/win/handle.h" | 39 #include "util/win/handle.h" |
| 40 #include "util/win/initial_client_data.h" | 40 #include "util/win/initial_client_data.h" |
| 41 #include "util/win/nt_internals.h" | 41 #include "util/win/nt_internals.h" |
| 42 #include "util/win/ntstatus_logging.h" | 42 #include "util/win/ntstatus_logging.h" |
| 43 #include "util/win/process_info.h" | 43 #include "util/win/process_info.h" |
| 44 #include "util/win/registration_protocol_win.h" | 44 #include "util/win/registration_protocol_win.h" |
| 45 #include "util/win/safe_terminate_process.h" |
| 45 #include "util/win/scoped_process_suspend.h" | 46 #include "util/win/scoped_process_suspend.h" |
| 46 #include "util/win/termination_codes.h" | 47 #include "util/win/termination_codes.h" |
| 47 #include "util/win/xp_compat.h" | 48 #include "util/win/xp_compat.h" |
| 48 | 49 |
| 49 namespace crashpad { | 50 namespace crashpad { |
| 50 | 51 |
| 51 namespace { | 52 namespace { |
| 52 | 53 |
| 53 // This handle is never closed. This is used to signal to the server that a dump | 54 // This handle is never closed. This is used to signal to the server that a dump |
| 54 // should be taken in the event of a crash. | 55 // should be taken in the event of a crash. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 LONG status = __asan_unhandled_exception_filter(exception_pointers); | 120 LONG status = __asan_unhandled_exception_filter(exception_pointers); |
| 120 if (status != EXCEPTION_CONTINUE_SEARCH) | 121 if (status != EXCEPTION_CONTINUE_SEARCH) |
| 121 return status; | 122 return status; |
| 122 #endif | 123 #endif |
| 123 | 124 |
| 124 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) { | 125 if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) { |
| 125 // If we know for certain that the handler has failed to start, then abort | 126 // If we know for certain that the handler has failed to start, then abort |
| 126 // here, rather than trying to signal to a handler that will never arrive, | 127 // here, rather than trying to signal to a handler that will never arrive, |
| 127 // and then sleeping unnecessarily. | 128 // and then sleeping unnecessarily. |
| 128 LOG(ERROR) << "crash server failed to launch, self-terminating"; | 129 LOG(ERROR) << "crash server failed to launch, self-terminating"; |
| 129 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump); | 130 SafeTerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump); |
| 130 return EXCEPTION_CONTINUE_SEARCH; | 131 return EXCEPTION_CONTINUE_SEARCH; |
| 131 } | 132 } |
| 132 | 133 |
| 133 // Otherwise, we know the handler startup has succeeded, and we can continue. | 134 // Otherwise, we know the handler startup has succeeded, and we can continue. |
| 134 | 135 |
| 135 // Tracks whether a thread has already entered UnhandledExceptionHandler. | 136 // Tracks whether a thread has already entered UnhandledExceptionHandler. |
| 136 static base::subtle::AtomicWord have_crashed; | 137 static base::subtle::AtomicWord have_crashed; |
| 137 | 138 |
| 138 // This is a per-process handler. While this handler is being invoked, other | 139 // This is a per-process handler. While this handler is being invoked, other |
| 139 // threads are still executing as usual, so multiple threads could enter at | 140 // threads are still executing as usual, so multiple threads could enter at |
| (...skipping 24 matching lines...) Expand all Loading... |
| 164 // Time to wait for the handler to create a dump. | 165 // Time to wait for the handler to create a dump. |
| 165 const DWORD kMillisecondsUntilTerminate = 60 * 1000; | 166 const DWORD kMillisecondsUntilTerminate = 60 * 1000; |
| 166 | 167 |
| 167 // Sleep for a while to allow it to process us. Eventually, we terminate | 168 // Sleep for a while to allow it to process us. Eventually, we terminate |
| 168 // ourselves in case the crash server is gone, so that we don't leave zombies | 169 // ourselves in case the crash server is gone, so that we don't leave zombies |
| 169 // around. This would ideally never happen. | 170 // around. This would ideally never happen. |
| 170 Sleep(kMillisecondsUntilTerminate); | 171 Sleep(kMillisecondsUntilTerminate); |
| 171 | 172 |
| 172 LOG(ERROR) << "crash server did not respond, self-terminating"; | 173 LOG(ERROR) << "crash server did not respond, self-terminating"; |
| 173 | 174 |
| 174 TerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump); | 175 SafeTerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump); |
| 175 | 176 |
| 176 return EXCEPTION_CONTINUE_SEARCH; | 177 return EXCEPTION_CONTINUE_SEARCH; |
| 177 } | 178 } |
| 178 | 179 |
| 179 void HandleAbortSignal(int signum) { | 180 void HandleAbortSignal(int signum) { |
| 180 DCHECK_EQ(signum, SIGABRT); | 181 DCHECK_EQ(signum, SIGABRT); |
| 181 | 182 |
| 182 CONTEXT context; | 183 CONTEXT context; |
| 183 CaptureContext(&context); | 184 CaptureContext(&context); |
| 184 | 185 |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 // here, as we would otherwise wait indefinitely for the | 727 // here, as we would otherwise wait indefinitely for the |
| 727 // g_non_crash_dump_done event that would never be signalled. | 728 // g_non_crash_dump_done event that would never be signalled. |
| 728 LOG(ERROR) << "crash server failed to launch, no dump captured"; | 729 LOG(ERROR) << "crash server failed to launch, no dump captured"; |
| 729 return; | 730 return; |
| 730 } | 731 } |
| 731 | 732 |
| 732 // In the non-crashing case, we aren't concerned about avoiding calls into | 733 // In the non-crashing case, we aren't concerned about avoiding calls into |
| 733 // Win32 APIs, so just use regular locking here in case of multiple threads | 734 // Win32 APIs, so just use regular locking here in case of multiple threads |
| 734 // calling this function. If a crash occurs while we're in here, the worst | 735 // calling this function. If a crash occurs while we're in here, the worst |
| 735 // that can happen is that the server captures a partial dump for this path | 736 // that can happen is that the server captures a partial dump for this path |
| 736 // because on the other thread gathering a crash dump, it TerminateProcess()d, | 737 // because another thread’s crash processing finished and the process was |
| 737 // causing this one to abort. | 738 // terminated before this thread’s non-crash processing could be completed. |
| 738 base::AutoLock lock(*g_non_crash_dump_lock); | 739 base::AutoLock lock(*g_non_crash_dump_lock); |
| 739 | 740 |
| 740 // Create a fake EXCEPTION_POINTERS to give the handler something to work | 741 // Create a fake EXCEPTION_POINTERS to give the handler something to work |
| 741 // with. | 742 // with. |
| 742 EXCEPTION_POINTERS exception_pointers = {}; | 743 EXCEPTION_POINTERS exception_pointers = {}; |
| 743 | 744 |
| 744 // This is logically const, but EXCEPTION_POINTERS does not declare it as | 745 // This is logically const, but EXCEPTION_POINTERS does not declare it as |
| 745 // const, so we have to cast that away from the argument. | 746 // const, so we have to cast that away from the argument. |
| 746 exception_pointers.ContextRecord = const_cast<CONTEXT*>(&context); | 747 exception_pointers.ContextRecord = const_cast<CONTEXT*>(&context); |
| 747 | 748 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 770 PLOG_IF(ERROR, !set_event_result) << "SetEvent"; | 771 PLOG_IF(ERROR, !set_event_result) << "SetEvent"; |
| 771 | 772 |
| 772 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); | 773 DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE); |
| 773 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; | 774 PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject"; |
| 774 } | 775 } |
| 775 | 776 |
| 776 // static | 777 // static |
| 777 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) { | 778 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) { |
| 778 if (g_signal_exception == INVALID_HANDLE_VALUE) { | 779 if (g_signal_exception == INVALID_HANDLE_VALUE) { |
| 779 LOG(ERROR) << "not connected"; | 780 LOG(ERROR) << "not connected"; |
| 780 TerminateProcess(GetCurrentProcess(), | 781 SafeTerminateProcess(GetCurrentProcess(), |
| 781 kTerminationCodeNotConnectedToHandler); | 782 kTerminationCodeNotConnectedToHandler); |
| 782 return; | 783 return; |
| 783 } | 784 } |
| 784 | 785 |
| 785 // We don't need to check for handler startup here, as | 786 // We don't need to check for handler startup here, as |
| 786 // UnhandledExceptionHandler() necessarily does that. | 787 // UnhandledExceptionHandler() necessarily does that. |
| 787 | 788 |
| 788 UnhandledExceptionHandler(exception_pointers); | 789 UnhandledExceptionHandler(exception_pointers); |
| 789 } | 790 } |
| 790 | 791 |
| 791 bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process, | 792 bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process, |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 status = NtClose(injected_thread); | 1026 status = NtClose(injected_thread); |
| 1026 if (!NT_SUCCESS(status)) { | 1027 if (!NT_SUCCESS(status)) { |
| 1027 NTSTATUS_LOG(ERROR, status) << "NtClose"; | 1028 NTSTATUS_LOG(ERROR, status) << "NtClose"; |
| 1028 result = false; | 1029 result = false; |
| 1029 } | 1030 } |
| 1030 | 1031 |
| 1031 return result; | 1032 return result; |
| 1032 } | 1033 } |
| 1033 | 1034 |
| 1034 } // namespace crashpad | 1035 } // namespace crashpad |
| OLD | NEW |