| 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 |