// static void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) { static bool s_first_run = true; // Load the dbghelp dll now, instead of waiting for the crash. // Less potential for stack mangling if (s_first_run) { // First, try loading from the directory that the app resides in. std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); HMODULE hDll = NULL; hDll = LoadLibraryA(local_dll_name.c_str()); if (!hDll) { hDll = LoadLibrary(L"dbghelp.dll"); } if (!hDll) { LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; } else { f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); if (!f_mdwp) { FreeLibrary(hDll); hDll = NULL; } } gEmergencyMemoryReserve.reserve(); s_first_run = false; } // Try to get Tool Help library functions. HMODULE hKernel32; hKernel32 = GetModuleHandle(_T("KERNEL32")); CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; prev_filter = SetUnhandledExceptionFilter(filter_func); // *REMOVE:Mani //PreventSetUnhandledExceptionFilter(); if(prev_filter != gFilterFunc) { LL_WARNS("AppInit") << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; } gFilterFunc = filter_func; }
// static void LLWinDebug::generateMinidump(struct _EXCEPTION_POINTERS *exception_infop) { std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException"); if (exception_infop) { // Since there is exception info... Release the hounds. gEmergencyMemoryReserve.release(); _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = exception_infop; ExInfo.ClientPointers = NULL; writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLife.dmp"); } }
// static void LLWinDebug::init() { static bool s_first_run = true; // Load the dbghelp dll now, instead of waiting for the crash. // Less potential for stack mangling // Don't install vectored exception handler if being debugged. if(IsDebuggerPresent()) return; if (s_first_run) { // First, try loading from the directory that the app resides in. std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); HMODULE hDll = NULL; hDll = LoadLibraryA(local_dll_name.c_str()); if (!hDll) { hDll = LoadLibrary(L"dbghelp.dll"); } if (!hDll) { LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; } else { f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); if (!f_mdwp) { FreeLibrary(hDll); hDll = NULL; } } gEmergencyMemoryReserve.reserve(); s_first_run = false; // Add this exeption hanlder to save windows style minidump. AddVectoredExceptionHandler(0, &vectoredHandler); } }
void LLWinDebug::cleanup () { gEmergencyMemoryReserve.release(); }
// static void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) { // *NOTE:Mani - This method is no longer the exception handler. // Its called from viewer_windows_exception_handler() and other places. // // Let go of a bunch of reserved memory to give library calls etc // a chance to execute normally in the case that we ran out of // memory. // LLSD info; std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "PhoenixViewerException"); std::string log_path = dump_path + ".log"; if (exception_infop) { // Since there is exception info... Release the hounds. gEmergencyMemoryReserve.release(); if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) { _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = exception_infop; ExInfo.ClientPointers = NULL; writeDumpToFile(MiniDumpNormal, &ExInfo, "PhoenixViewer.dmp"); writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "PhoenixViewerPlus.dmp"); } info = Get_Exception_Info(exception_infop); } LLSD threads; std::vector<DWORD> thread_ids; GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); for(std::vector<DWORD>::iterator th_itr = thread_ids.begin(); th_itr != thread_ids.end(); ++th_itr) { LLSD thread_info; if(*th_itr != GetCurrentThreadId()) { GetThreadCallStack(*th_itr, thread_info); } if(thread_info) { threads[llformat("ID %d", *th_itr)] = thread_info; } } info["Threads"] = threads; llofstream out_file(log_path); LLSDSerialize::toPrettyXML(info, out_file); out_file.close(); }