diff options
author | Jacek Antonelli | 2008-08-15 23:45:50 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:50 -0500 |
commit | 2a4dea528f670b9bb1f77ef27a8a1dd16603d114 (patch) | |
tree | 95c68e362703c9099d571ecbdc6142b1cda1e005 /linden/indra/newview/llwindebug.cpp | |
parent | Second Life viewer sources 1.20.6 (diff) | |
download | meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.zip meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.gz meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.bz2 meta-impy-2a4dea528f670b9bb1f77ef27a8a1dd16603d114.tar.xz |
Second Life viewer sources 1.20.7
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llwindebug.cpp | 154 |
1 files changed, 67 insertions, 87 deletions
diff --git a/linden/indra/newview/llwindebug.cpp b/linden/indra/newview/llwindebug.cpp index 1b52a14..aba637c 100644 --- a/linden/indra/newview/llwindebug.cpp +++ b/linden/indra/newview/llwindebug.cpp | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | #include <tchar.h> | 36 | #include <tchar.h> |
37 | #include <tlhelp32.h> | 37 | #include <tlhelp32.h> |
38 | #include "llappviewer.h" | ||
39 | #include "llwindebug.h" | 38 | #include "llwindebug.h" |
40 | #include "llviewercontrol.h" | 39 | #include "llviewercontrol.h" |
41 | #include "lldir.h" | 40 | #include "lldir.h" |
@@ -106,6 +105,8 @@ MINIDUMPWRITEDUMP f_mdwp = NULL; | |||
106 | 105 | ||
107 | #undef UNICODE | 106 | #undef UNICODE |
108 | 107 | ||
108 | static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; | ||
109 | |||
109 | HMODULE hDbgHelp; | 110 | HMODULE hDbgHelp; |
110 | 111 | ||
111 | // Tool Help functions. | 112 | // Tool Help functions. |
@@ -554,14 +555,13 @@ void LLMemoryReserve::release() | |||
554 | static LLMemoryReserve gEmergencyMemoryReserve; | 555 | static LLMemoryReserve gEmergencyMemoryReserve; |
555 | 556 | ||
556 | // static | 557 | // static |
557 | BOOL LLWinDebug::setupExceptionHandler() | 558 | void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) |
558 | { | 559 | { |
559 | 560 | ||
560 | static BOOL s_first_run = TRUE; | 561 | static bool s_first_run = true; |
561 | // Load the dbghelp dll now, instead of waiting for the crash. | 562 | // Load the dbghelp dll now, instead of waiting for the crash. |
562 | // Less potential for stack mangling | 563 | // Less potential for stack mangling |
563 | 564 | ||
564 | BOOL ok = TRUE; | ||
565 | if (s_first_run) | 565 | if (s_first_run) |
566 | { | 566 | { |
567 | // First, try loading from the directory that the app resides in. | 567 | // First, try loading from the directory that the app resides in. |
@@ -576,15 +576,7 @@ BOOL LLWinDebug::setupExceptionHandler() | |||
576 | 576 | ||
577 | if (!hDll) | 577 | if (!hDll) |
578 | { | 578 | { |
579 | llwarns << "Couldn't find dbghelp.dll!" << llendl; | 579 | LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; |
580 | |||
581 | std::string msg = "Couldn't find dbghelp.dll at "; | ||
582 | msg += local_dll_name; | ||
583 | msg += "!\n"; | ||
584 | |||
585 | //write_debug(msg.c_str()); | ||
586 | |||
587 | ok = FALSE; | ||
588 | } | 580 | } |
589 | else | 581 | else |
590 | { | 582 | { |
@@ -592,18 +584,15 @@ BOOL LLWinDebug::setupExceptionHandler() | |||
592 | 584 | ||
593 | if (!f_mdwp) | 585 | if (!f_mdwp) |
594 | { | 586 | { |
595 | //write_debug("No MiniDumpWriteDump!\n"); | ||
596 | FreeLibrary(hDll); | 587 | FreeLibrary(hDll); |
597 | hDll = NULL; | 588 | hDll = NULL; |
598 | ok = FALSE; | ||
599 | } | 589 | } |
600 | } | 590 | } |
601 | 591 | ||
602 | gEmergencyMemoryReserve.reserve(); | 592 | gEmergencyMemoryReserve.reserve(); |
603 | } | ||
604 | 593 | ||
605 | LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; | 594 | s_first_run = false; |
606 | prev_filter = SetUnhandledExceptionFilter(LLWinDebug::handleException); | 595 | } |
607 | 596 | ||
608 | // Try to get Tool Help library functions. | 597 | // Try to get Tool Help library functions. |
609 | HMODULE hKernel32; | 598 | HMODULE hKernel32; |
@@ -612,26 +601,44 @@ BOOL LLWinDebug::setupExceptionHandler() | |||
612 | Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); | 601 | Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); |
613 | Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); | 602 | Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); |
614 | 603 | ||
615 | if (s_first_run) | 604 | LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; |
605 | prev_filter = SetUnhandledExceptionFilter(filter_func); | ||
606 | |||
607 | if(prev_filter != gFilterFunc) | ||
616 | { | 608 | { |
617 | // We're fine, this is the first run. | 609 | LL_WARNS("AppInit") |
618 | s_first_run = FALSE; | 610 | << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; |
619 | return ok; | ||
620 | } | 611 | } |
621 | if (!prev_filter) | 612 | |
613 | gFilterFunc = filter_func; | ||
614 | } | ||
615 | |||
616 | bool LLWinDebug::checkExceptionHandler() | ||
617 | { | ||
618 | bool ok = true; | ||
619 | LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; | ||
620 | prev_filter = SetUnhandledExceptionFilter(gFilterFunc); | ||
621 | |||
622 | if (prev_filter != gFilterFunc) | ||
622 | { | 623 | { |
623 | llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl; | 624 | LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; |
624 | ok = FALSE; | 625 | ok = false; |
625 | } | 626 | } |
626 | if (prev_filter != LLWinDebug::handleException) | 627 | |
628 | if (prev_filter == NULL) | ||
627 | { | 629 | { |
628 | llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl; | ||
629 | ok = FALSE; | 630 | ok = FALSE; |
631 | if (gFilterFunc == NULL) | ||
632 | { | ||
633 | LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; | ||
634 | } | ||
635 | else | ||
636 | { | ||
637 | LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; | ||
638 | } | ||
630 | } | 639 | } |
631 | 640 | ||
632 | return ok; | 641 | return ok; |
633 | // Internal builds don't mess with exception handling. | ||
634 | //return TRUE; | ||
635 | } | 642 | } |
636 | 643 | ||
637 | void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename) | 644 | void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename) |
@@ -644,7 +651,7 @@ void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMAT | |||
644 | else | 651 | else |
645 | { | 652 | { |
646 | std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, | 653 | std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, |
647 | filename); | 654 | filename); |
648 | 655 | ||
649 | HANDLE hFile = CreateFileA(dump_path.c_str(), | 656 | HANDLE hFile = CreateFileA(dump_path.c_str(), |
650 | GENERIC_WRITE, | 657 | GENERIC_WRITE, |
@@ -672,20 +679,26 @@ void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMAT | |||
672 | } | 679 | } |
673 | 680 | ||
674 | // static | 681 | // static |
675 | LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop) | 682 | void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) |
676 | { | 683 | { |
677 | // *NOTE:Mani - This method is no longer the initial exception handler. | 684 | // *NOTE:Mani - This method is no longer the exception handler. |
678 | // It is called from viewer_windows_exception_handler() and other places. | 685 | // Its called from viewer_windows_exception_handler() and other places. |
679 | 686 | ||
680 | // | 687 | // |
681 | // Let go of a bunch of reserved memory to give library calls etc | 688 | // Let go of a bunch of reserved memory to give library calls etc |
682 | // a chance to execute normally in the case that we ran out of | 689 | // a chance to execute normally in the case that we ran out of |
683 | // memory. | 690 | // memory. |
684 | // | 691 | // |
685 | gEmergencyMemoryReserve.release(); | 692 | LLSD info; |
693 | std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, | ||
694 | "SecondLifeException"); | ||
695 | std::string log_path = dump_path + ".log"; | ||
686 | 696 | ||
687 | if (exception_infop) | 697 | if (exception_infop) |
688 | { | 698 | { |
699 | // Since there is exception info... Release the hounds. | ||
700 | gEmergencyMemoryReserve.release(); | ||
701 | |||
689 | if(gSavedSettings.getControl("SaveMinidump") != NULL && gSavedSettings.getBOOL("SaveMinidump")) | 702 | if(gSavedSettings.getControl("SaveMinidump") != NULL && gSavedSettings.getBOOL("SaveMinidump")) |
690 | { | 703 | { |
691 | _MINIDUMP_EXCEPTION_INFORMATION ExInfo; | 704 | _MINIDUMP_EXCEPTION_INFORMATION ExInfo; |
@@ -698,67 +711,34 @@ LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop) | |||
698 | writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); | 711 | writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); |
699 | } | 712 | } |
700 | 713 | ||
701 | |||
702 | std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, | ||
703 | "SecondLifeException"); | ||
704 | |||
705 | std::string log_path = dump_path + ".log"; | ||
706 | |||
707 | LLSD info; | ||
708 | info = Get_Exception_Info(exception_infop); | 714 | info = Get_Exception_Info(exception_infop); |
715 | } | ||
709 | 716 | ||
717 | LLSD threads; | ||
718 | std::vector<DWORD> thread_ids; | ||
719 | GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); | ||
710 | 720 | ||
711 | LLSD threads; | 721 | for(std::vector<DWORD>::iterator th_itr = thread_ids.begin(); |
712 | std::vector<DWORD> thread_ids; | 722 | th_itr != thread_ids.end(); |
713 | GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); | 723 | ++th_itr) |
714 | 724 | { | |
715 | for(std::vector<DWORD>::iterator th_itr = thread_ids.begin(); | 725 | LLSD thread_info; |
716 | th_itr != thread_ids.end(); | 726 | if(*th_itr != GetCurrentThreadId()) |
717 | ++th_itr) | ||
718 | { | 727 | { |
719 | LLSD thread_info; | 728 | GetThreadCallStack(*th_itr, thread_info); |
720 | if(*th_itr != GetCurrentThreadId()) | ||
721 | { | ||
722 | GetThreadCallStack(*th_itr, thread_info); | ||
723 | } | ||
724 | |||
725 | if(thread_info) | ||
726 | { | ||
727 | |||
728 | threads[llformat("ID %d", *th_itr)] = thread_info; | ||
729 | } | ||
730 | } | 729 | } |
731 | 730 | ||
731 | if(thread_info) | ||
732 | { | ||
733 | threads[llformat("ID %d", *th_itr)] = thread_info; | ||
734 | } | ||
735 | } | ||
732 | 736 | ||
733 | info["Threads"] = threads; | 737 | info["Threads"] = threads; |
734 | |||
735 | if (info) | ||
736 | { | ||
737 | std::ofstream out_file(log_path.c_str()); | ||
738 | LLSDSerialize::toPrettyXML(info, out_file); | ||
739 | out_file.close(); | ||
740 | } | ||
741 | } | ||
742 | else | ||
743 | { | ||
744 | // We're calling this due to a network error, not due to an actual exception. | ||
745 | // It doesn't realy matter what we return. | ||
746 | return EXCEPTION_CONTINUE_SEARCH; | ||
747 | } | ||
748 | |||
749 | //handle viewer crash must be called here since | ||
750 | //we don't return handling of the application | ||
751 | //back to the process. | ||
752 | LLAppViewer::handleViewerCrash(); | ||
753 | 738 | ||
754 | // | 739 | std::ofstream out_file(log_path.c_str()); |
755 | // At this point, we always want to exit the app. There's no graceful | 740 | LLSDSerialize::toPrettyXML(info, out_file); |
756 | // recovery for an unhandled exception. | 741 | out_file.close(); |
757 | // | ||
758 | // Just kill the process. | ||
759 | LONG retval = EXCEPTION_EXECUTE_HANDLER; | ||
760 | |||
761 | return retval; | ||
762 | } | 742 | } |
763 | 743 | ||
764 | #endif | 744 | #endif |