PageRenderTime 73ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llwindebug.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 191 lines | 122 code | 31 blank | 38 comment | 15 complexity | 19c343004ff573d8636b5bbfabb8847e MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llwindebug.cpp
  3. * @brief Windows debugging functions
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llwindebug.h"
  28. #include "lldir.h"
  29. // based on dbghelp.h
  30. typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
  31. CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  32. CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
  33. CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
  34. );
  35. MINIDUMPWRITEDUMP f_mdwp = NULL;
  36. class LLMemoryReserve {
  37. public:
  38. LLMemoryReserve();
  39. ~LLMemoryReserve();
  40. void reserve();
  41. void release();
  42. protected:
  43. unsigned char *mReserve;
  44. static const size_t MEMORY_RESERVATION_SIZE;
  45. };
  46. LLMemoryReserve::LLMemoryReserve() :
  47. mReserve(NULL)
  48. {
  49. };
  50. LLMemoryReserve::~LLMemoryReserve()
  51. {
  52. release();
  53. }
  54. // I dunno - this just seemed like a pretty good value.
  55. const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024;
  56. void LLMemoryReserve::reserve()
  57. {
  58. if(NULL == mReserve)
  59. mReserve = new unsigned char[MEMORY_RESERVATION_SIZE];
  60. };
  61. void LLMemoryReserve::release()
  62. {
  63. delete [] mReserve;
  64. mReserve = NULL;
  65. };
  66. static LLMemoryReserve gEmergencyMemoryReserve;
  67. LONG NTAPI vectoredHandler(PEXCEPTION_POINTERS exception_infop)
  68. {
  69. LLWinDebug::instance().generateMinidump(exception_infop);
  70. return EXCEPTION_CONTINUE_SEARCH;
  71. }
  72. // static
  73. void LLWinDebug::init()
  74. {
  75. static bool s_first_run = true;
  76. // Load the dbghelp dll now, instead of waiting for the crash.
  77. // Less potential for stack mangling
  78. // Don't install vectored exception handler if being debugged.
  79. if(IsDebuggerPresent()) return;
  80. if (s_first_run)
  81. {
  82. // First, try loading from the directory that the app resides in.
  83. std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir());
  84. HMODULE hDll = NULL;
  85. hDll = LoadLibraryA(local_dll_name.c_str());
  86. if (!hDll)
  87. {
  88. hDll = LoadLibrary(L"dbghelp.dll");
  89. }
  90. if (!hDll)
  91. {
  92. LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL;
  93. }
  94. else
  95. {
  96. f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump");
  97. if (!f_mdwp)
  98. {
  99. FreeLibrary(hDll);
  100. hDll = NULL;
  101. }
  102. }
  103. gEmergencyMemoryReserve.reserve();
  104. s_first_run = false;
  105. // Add this exeption hanlder to save windows style minidump.
  106. AddVectoredExceptionHandler(0, &vectoredHandler);
  107. }
  108. }
  109. void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename)
  110. {
  111. // Temporary fix to switch out the code that writes the DMP file.
  112. // Fix coming that doesn't write a mini dump file for regular C++ exceptions.
  113. const bool enable_write_dump_file = false;
  114. if ( enable_write_dump_file )
  115. {
  116. if(f_mdwp == NULL || gDirUtilp == NULL)
  117. {
  118. return;
  119. }
  120. else
  121. {
  122. std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename);
  123. HANDLE hFile = CreateFileA(dump_path.c_str(),
  124. GENERIC_WRITE,
  125. FILE_SHARE_WRITE,
  126. NULL,
  127. CREATE_ALWAYS,
  128. FILE_ATTRIBUTE_NORMAL,
  129. NULL);
  130. if (hFile != INVALID_HANDLE_VALUE)
  131. {
  132. // Write the dump, ignoring the return value
  133. f_mdwp(GetCurrentProcess(),
  134. GetCurrentProcessId(),
  135. hFile,
  136. type,
  137. ExInfop,
  138. NULL,
  139. NULL);
  140. CloseHandle(hFile);
  141. }
  142. }
  143. }
  144. }
  145. // static
  146. void LLWinDebug::generateMinidump(struct _EXCEPTION_POINTERS *exception_infop)
  147. {
  148. std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
  149. "SecondLifeException");
  150. if (exception_infop)
  151. {
  152. // Since there is exception info... Release the hounds.
  153. gEmergencyMemoryReserve.release();
  154. _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
  155. ExInfo.ThreadId = ::GetCurrentThreadId();
  156. ExInfo.ExceptionPointers = exception_infop;
  157. ExInfo.ClientPointers = NULL;
  158. writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLife.dmp");
  159. }
  160. }