| 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 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 | 483 |
| 484 // Make up an exception record for the current thread and CPU context | 484 // Make up an exception record for the current thread and CPU context |
| 485 // to make it possible for the crash processor to classify these | 485 // to make it possible for the crash processor to classify these |
| 486 // as do regular crashes, and to make it humane for developers to | 486 // as do regular crashes, and to make it humane for developers to |
| 487 // analyze them. | 487 // analyze them. |
| 488 EXCEPTION_RECORD exception_record = {}; | 488 EXCEPTION_RECORD exception_record = {}; |
| 489 CONTEXT exception_context = {}; | 489 CONTEXT exception_context = {}; |
| 490 EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; | 490 EXCEPTION_POINTERS exception_ptrs = { &exception_record, &exception_context }; |
| 491 RtlCaptureContext(&exception_context); | 491 RtlCaptureContext(&exception_context); |
| 492 exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; | 492 exception_record.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION; |
| 493 | 493 |
| 494 // We store pointers to the the expression and function strings, | 494 // We store pointers to the the expression and function strings, |
| 495 // and the line as exception parameters to make them easy to | 495 // and the line as exception parameters to make them easy to |
| 496 // access by the developer on the far side. | 496 // access by the developer on the far side. |
| 497 exception_record.NumberParameters = 3; | 497 exception_record.NumberParameters = 3; |
| 498 exception_record.ExceptionInformation[0] = | 498 exception_record.ExceptionInformation[0] = |
| 499 reinterpret_cast<ULONG_PTR>(&assertion.expression); | 499 reinterpret_cast<ULONG_PTR>(&assertion.expression); |
| 500 exception_record.ExceptionInformation[1] = | 500 exception_record.ExceptionInformation[1] = |
| 501 reinterpret_cast<ULONG_PTR>(&assertion.file); | 501 reinterpret_cast<ULONG_PTR>(&assertion.file); |
| 502 exception_record.ExceptionInformation[2] = assertion.line; | 502 exception_record.ExceptionInformation[2] = assertion.line; |
| 503 | 503 |
| 504 bool success = false; | 504 bool success = false; |
| 505 // In case of out-of-process dump generation, directly call | 505 // In case of out-of-process dump generation, directly call |
| 506 // WriteMinidumpWithException since there is no separate thread running. | 506 // WriteMinidumpWithException since there is no separate thread running. |
| 507 if (current_handler->IsOutOfProcess()) { | 507 if (current_handler->IsOutOfProcess()) { |
| 508 success = current_handler->WriteMinidumpWithException( | 508 success = current_handler->WriteMinidumpWithException( |
| 509 GetCurrentThreadId(), | 509 GetCurrentThreadId(), |
| 510 &exception_ptrs, | 510 &exception_ptrs, |
| 511 &assertion); | 511 &assertion); |
| 512 } else { | 512 } else { |
| 513 success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, | 513 success = current_handler->WriteMinidumpOnHandlerThread(&exception_ptrs, |
| 514 &assertion); | 514 &assertion); |
| 515 } | 515 } |
| 516 | 516 |
| 517 if (!success) { | 517 if (!success) { |
| 518 if (current_handler->previous_iph_) { | 518 if (current_handler->previous_iph_) { |
| 519 // The handler didn't fully handle the exception. Give it to the | 519 // The handler didn't fully handle the exception. Give it to the |
| 520 // previous invalid parameter handler. | 520 // previous invalid parameter handler. |
| 521 current_handler->previous_iph_(expression, | 521 current_handler->previous_iph_(expression, |
| 522 function, | 522 function, |
| 523 file, | 523 file, |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 // was called as a result of an exception, returning false will cause | 661 // was called as a result of an exception, returning false will cause |
| 662 // HandleException to call any previous handler or return | 662 // HandleException to call any previous handler or return |
| 663 // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear | 663 // EXCEPTION_CONTINUE_SEARCH on the exception thread, allowing it to appear |
| 664 // as though this handler were not present at all. | 664 // as though this handler were not present at all. |
| 665 if (filter_ && !filter_(callback_context_, exinfo, assertion)) { | 665 if (filter_ && !filter_(callback_context_, exinfo, assertion)) { |
| 666 return false; | 666 return false; |
| 667 } | 667 } |
| 668 | 668 |
| 669 bool success = false; | 669 bool success = false; |
| 670 if (IsOutOfProcess()) { | 670 if (IsOutOfProcess()) { |
| 671 // Use the EXCEPTION_POINTERS overload for RequestDump if | 671 success = crash_generation_client_->RequestDump(exinfo, assertion); |
| 672 // both exinfo and assertion are NULL. | |
| 673 if (!assertion) { | |
| 674 success = crash_generation_client_->RequestDump(exinfo); | |
| 675 } else { | |
| 676 success = crash_generation_client_->RequestDump(assertion); | |
| 677 } | |
| 678 } else { | 672 } else { |
| 679 if (minidump_write_dump_) { | 673 if (minidump_write_dump_) { |
| 680 HANDLE dump_file = CreateFile(next_minidump_path_c_, | 674 HANDLE dump_file = CreateFile(next_minidump_path_c_, |
| 681 GENERIC_WRITE, | 675 GENERIC_WRITE, |
| 682 0, // no sharing | 676 0, // no sharing |
| 683 NULL, | 677 NULL, |
| 684 CREATE_NEW, // fail if exists | 678 CREATE_NEW, // fail if exists |
| 685 FILE_ATTRIBUTE_NORMAL, | 679 FILE_ATTRIBUTE_NORMAL, |
| 686 NULL); | 680 NULL); |
| 687 if (dump_file != INVALID_HANDLE_VALUE) { | 681 if (dump_file != INVALID_HANDLE_VALUE) { |
| 688 MINIDUMP_EXCEPTION_INFORMATION except_info; | 682 MINIDUMP_EXCEPTION_INFORMATION except_info; |
| 689 except_info.ThreadId = requesting_thread_id; | 683 except_info.ThreadId = requesting_thread_id; |
| 690 except_info.ExceptionPointers = exinfo; | 684 except_info.ExceptionPointers = exinfo; |
| 691 except_info.ClientPointers = FALSE; | 685 except_info.ClientPointers = FALSE; |
| 692 | 686 |
| 693 // Add an MDRawBreakpadInfo stream to the minidump, to provide additiona
l | 687 // Add an MDRawBreakpadInfo stream to the minidump, to provide |
| 694 // information about the exception handler to the Breakpad processor. T
he | 688 // additional information about the exception handler to the Breakpad |
| 695 // information will help the processor determine which threads are | 689 // processor. The information will help the processor determine which |
| 696 // relevant. The Breakpad processor does not require this information b
ut | 690 // threads are relevant. The Breakpad processor does not require this |
| 697 // can function better with Breakpad-generated dumps when it is present. | 691 // information but can function better with Breakpad-generated dumps |
| 698 // The native debugger is not harmed by the presence of this information
. | 692 // when it is present. The native debugger is not harmed by the |
| 693 // presence of this information. |
| 699 MDRawBreakpadInfo breakpad_info; | 694 MDRawBreakpadInfo breakpad_info; |
| 700 breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | | 695 breakpad_info.validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | |
| 701 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; | 696 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; |
| 702 breakpad_info.dump_thread_id = GetCurrentThreadId(); | 697 breakpad_info.dump_thread_id = GetCurrentThreadId(); |
| 703 breakpad_info.requesting_thread_id = requesting_thread_id; | 698 breakpad_info.requesting_thread_id = requesting_thread_id; |
| 704 | 699 |
| 705 // Leave room in user_stream_array for a possible assertion info stream. | 700 // Leave room in user_stream_array for a possible assertion info stream. |
| 706 MINIDUMP_USER_STREAM user_stream_array[2]; | 701 MINIDUMP_USER_STREAM user_stream_array[2]; |
| 707 user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; | 702 user_stream_array[0].Type = MD_BREAKPAD_INFO_STREAM; |
| 708 user_stream_array[0].BufferSize = sizeof(breakpad_info); | 703 user_stream_array[0].BufferSize = sizeof(breakpad_info); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 dump_path_c_, next_minidump_id_c_); | 754 dump_path_c_, next_minidump_id_c_); |
| 760 | 755 |
| 761 // remove when VC++7.1 is no longer supported | 756 // remove when VC++7.1 is no longer supported |
| 762 minidump_path[MAX_PATH - 1] = L'\0'; | 757 minidump_path[MAX_PATH - 1] = L'\0'; |
| 763 | 758 |
| 764 next_minidump_path_ = minidump_path; | 759 next_minidump_path_ = minidump_path; |
| 765 next_minidump_path_c_ = next_minidump_path_.c_str(); | 760 next_minidump_path_c_ = next_minidump_path_.c_str(); |
| 766 } | 761 } |
| 767 | 762 |
| 768 } // namespace google_breakpad | 763 } // namespace google_breakpad |
| OLD | NEW |