OLD | NEW |
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 // or registration with the server process failed. In either case, | 133 // or registration with the server process failed. In either case, |
134 // setup to do in-process crash generation. | 134 // setup to do in-process crash generation. |
135 | 135 |
136 // Set synchronization primitives and the handler thread. Each | 136 // Set synchronization primitives and the handler thread. Each |
137 // ExceptionHandler object gets its own handler thread because that's the | 137 // ExceptionHandler object gets its own handler thread because that's the |
138 // only way to reliably guarantee sufficient stack space in an exception, | 138 // only way to reliably guarantee sufficient stack space in an exception, |
139 // and it allows an easy way to get a snapshot of the requesting thread's | 139 // and it allows an easy way to get a snapshot of the requesting thread's |
140 // context outside of an exception. | 140 // context outside of an exception. |
141 InitializeCriticalSection(&handler_critical_section_); | 141 InitializeCriticalSection(&handler_critical_section_); |
142 handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); | 142 handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); |
| 143 assert(handler_start_semaphore_ != NULL); |
| 144 |
143 handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); | 145 handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); |
| 146 assert(handler_finish_semaphore_ != NULL); |
144 | 147 |
145 DWORD thread_id; | 148 // Don't attempt to create the thread if we could not create the semaphores. |
146 handler_thread_ = CreateThread(NULL, // lpThreadAttributes | 149 if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) { |
147 kExceptionHandlerThreadInitialStackSize, | 150 DWORD thread_id; |
148 ExceptionHandlerThreadMain, | 151 handler_thread_ = CreateThread(NULL, // lpThreadAttributes |
149 this, // lpParameter | 152 kExceptionHandlerThreadInitialStackSize, |
150 0, // dwCreationFlags | 153 ExceptionHandlerThreadMain, |
151 &thread_id); | 154 this, // lpParameter |
| 155 0, // dwCreationFlags |
| 156 &thread_id); |
| 157 assert(handler_thread_ != NULL); |
| 158 } |
152 | 159 |
153 dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); | 160 dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); |
154 if (dbghelp_module_) { | 161 if (dbghelp_module_) { |
155 minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>( | 162 minidump_write_dump_ = reinterpret_cast<MiniDumpWriteDump_type>( |
156 GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); | 163 GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); |
157 } | 164 } |
158 | 165 |
159 // Load this library dynamically to not affect existing projects. Most | 166 // Load this library dynamically to not affect existing projects. Most |
160 // projects don't link against this directly, it's usually dynamically | 167 // projects don't link against this directly, it's usually dynamically |
161 // loaded by dependent code. | 168 // loaded by dependent code. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 DeleteCriticalSection(&handler_critical_section_); | 264 DeleteCriticalSection(&handler_critical_section_); |
258 CloseHandle(handler_start_semaphore_); | 265 CloseHandle(handler_start_semaphore_); |
259 CloseHandle(handler_finish_semaphore_); | 266 CloseHandle(handler_finish_semaphore_); |
260 } | 267 } |
261 } | 268 } |
262 | 269 |
263 // static | 270 // static |
264 DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { | 271 DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { |
265 ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter); | 272 ExceptionHandler* self = reinterpret_cast<ExceptionHandler *>(lpParameter); |
266 assert(self); | 273 assert(self); |
| 274 assert(self->handler_start_semaphore_ != NULL); |
| 275 assert(self->handler_finish_semaphore_ != NULL); |
267 | 276 |
268 while (true) { | 277 while (true) { |
269 if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == | 278 if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == |
270 WAIT_OBJECT_0) { | 279 WAIT_OBJECT_0) { |
271 // Perform the requested action. | 280 // Perform the requested action. |
272 self->handler_return_value_ = self->WriteMinidumpWithException( | 281 self->handler_return_value_ = self->WriteMinidumpWithException( |
273 self->requesting_thread_id_, self->exception_info_, self->assertion_); | 282 self->requesting_thread_id_, self->exception_info_, self->assertion_); |
274 | 283 |
275 // Allow the requesting thread to proceed. | 284 // Allow the requesting thread to proceed. |
276 ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); | 285 ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 // The handler either took care of the invalid parameter problem itself, | 521 // The handler either took care of the invalid parameter problem itself, |
513 // or passed it on to another handler. "Swallow" it by exiting, paralleling | 522 // or passed it on to another handler. "Swallow" it by exiting, paralleling |
514 // the behavior of "swallowing" exceptions. | 523 // the behavior of "swallowing" exceptions. |
515 exit(0); | 524 exit(0); |
516 } | 525 } |
517 | 526 |
518 bool ExceptionHandler::WriteMinidumpOnHandlerThread( | 527 bool ExceptionHandler::WriteMinidumpOnHandlerThread( |
519 EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { | 528 EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion) { |
520 EnterCriticalSection(&handler_critical_section_); | 529 EnterCriticalSection(&handler_critical_section_); |
521 | 530 |
| 531 // There isn't much we can do if the handler thread |
| 532 // was not successfully created. |
| 533 if (handler_thread_ == NULL) { |
| 534 LeaveCriticalSection(&handler_critical_section_); |
| 535 return false; |
| 536 } |
| 537 |
| 538 // The handler thread should only be created when the semaphores are valid. |
| 539 assert(handler_start_semaphore_ != NULL); |
| 540 assert(handler_finish_semaphore_ != NULL); |
| 541 |
522 // Set up data to be passed in to the handler thread. | 542 // Set up data to be passed in to the handler thread. |
523 requesting_thread_id_ = GetCurrentThreadId(); | 543 requesting_thread_id_ = GetCurrentThreadId(); |
524 exception_info_ = exinfo; | 544 exception_info_ = exinfo; |
525 assertion_ = assertion; | 545 assertion_ = assertion; |
526 | 546 |
527 // This causes the handler thread to call WriteMinidumpWithException. | 547 // This causes the handler thread to call WriteMinidumpWithException. |
528 ReleaseSemaphore(handler_start_semaphore_, 1, NULL); | 548 ReleaseSemaphore(handler_start_semaphore_, 1, NULL); |
529 | 549 |
530 // Wait until WriteMinidumpWithException is done and collect its return value. | 550 // Wait until WriteMinidumpWithException is done and collect its return value. |
531 WaitForSingleObject(handler_finish_semaphore_, INFINITE); | 551 WaitForSingleObject(handler_finish_semaphore_, INFINITE); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 dump_path_c_, next_minidump_id_c_); | 695 dump_path_c_, next_minidump_id_c_); |
676 | 696 |
677 // remove when VC++7.1 is no longer supported | 697 // remove when VC++7.1 is no longer supported |
678 minidump_path[MAX_PATH - 1] = L'\0'; | 698 minidump_path[MAX_PATH - 1] = L'\0'; |
679 | 699 |
680 next_minidump_path_ = minidump_path; | 700 next_minidump_path_ = minidump_path; |
681 next_minidump_path_c_ = next_minidump_path_.c_str(); | 701 next_minidump_path_c_ = next_minidump_path_.c_str(); |
682 } | 702 } |
683 | 703 |
684 } // namespace google_breakpad | 704 } // namespace google_breakpad |
OLD | NEW |