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 |