aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llwindebug.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llwindebug.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llwindebug.cpp')
-rw-r--r--linden/indra/newview/llwindebug.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/linden/indra/newview/llwindebug.cpp b/linden/indra/newview/llwindebug.cpp
new file mode 100644
index 0000000..772ded4
--- /dev/null
+++ b/linden/indra/newview/llwindebug.cpp
@@ -0,0 +1,273 @@
1/**
2 * @file llwindebug.cpp
3 * @brief Windows debugging functions
4 *
5 * Copyright (c) 2004-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#ifdef LL_WINDOWS
31
32#include "llwindebug.h"
33#include "llviewercontrol.h"
34#include "lldir.h"
35
36// From viewer.h
37extern BOOL gInProductionGrid;
38
39extern void (*gCrashCallback)(void);
40extern void write_debug(const char *str);
41extern void write_debug(const std::string &str);
42
43// based on dbghelp.h
44typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
45 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
46 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
47 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
48 );
49
50MINIDUMPWRITEDUMP f_mdwp = NULL;
51
52
53
54class LLMemoryReserve {
55public:
56 LLMemoryReserve();
57 ~LLMemoryReserve();
58 void reserve();
59 void release();
60protected:
61 unsigned char *mReserve;
62 static const size_t MEMORY_RESERVATION_SIZE;
63};
64
65LLMemoryReserve::LLMemoryReserve() :
66 mReserve(NULL)
67{
68};
69
70LLMemoryReserve::~LLMemoryReserve()
71{
72 release();
73}
74
75// I dunno - this just seemed like a pretty good value.
76const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024;
77
78void LLMemoryReserve::reserve()
79{
80 if(NULL == mReserve)
81 mReserve = new unsigned char[MEMORY_RESERVATION_SIZE];
82};
83
84void LLMemoryReserve::release()
85{
86 delete [] mReserve;
87 mReserve = NULL;
88};
89
90static LLMemoryReserve gEmergencyMemoryReserve;
91
92// static
93BOOL LLWinDebug::setupExceptionHandler()
94{
95#ifdef LL_RELEASE_FOR_DOWNLOAD
96
97 static BOOL s_first_run = TRUE;
98 // Load the dbghelp dll now, instead of waiting for the crash.
99 // Less potential for stack mangling
100
101 BOOL ok = TRUE;
102 if (s_first_run)
103 {
104 // First, try loading from the directory that the app resides in.
105 std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir());
106
107 HMODULE hDll = NULL;
108 hDll = LoadLibraryA(local_dll_name.c_str());
109 if (!hDll)
110 {
111 hDll = LoadLibrary(L"dbghelp.dll");
112 }
113
114 if (!hDll)
115 {
116 llwarns << "Couldn't find dbghelp.dll!" << llendl;
117
118 std::string msg = "Couldn't find dbghelp.dll at ";
119 msg += local_dll_name;
120 msg += "!\n";
121
122 write_debug(msg.c_str());
123
124 ok = FALSE;
125 }
126 else
127 {
128 f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump");
129
130 if (!f_mdwp)
131 {
132 write_debug("No MiniDumpWriteDump!\n");
133 ok = FALSE;
134 }
135 }
136
137 gEmergencyMemoryReserve.reserve();
138 }
139
140 LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
141 prev_filter = SetUnhandledExceptionFilter(LLWinDebug::handleException);
142
143 if (s_first_run)
144 {
145 // We're fine, this is the first run.
146 s_first_run = FALSE;
147 return ok;
148 }
149 if (!prev_filter)
150 {
151 llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl;
152 ok = FALSE;
153 }
154 if (prev_filter != LLWinDebug::handleException)
155 {
156 llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl;
157 ok = FALSE;
158 }
159 return ok;
160#else
161 // Internal builds don't mess with exception handling.
162 return TRUE;
163#endif
164}
165
166void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename)
167{
168 if(f_mdwp == NULL)
169 {
170 write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n");
171 }
172 else if(gDirUtilp == NULL)
173 {
174 write_debug("No way to generate a minidump, no gDirUtilp!\n");
175 }
176 else
177 {
178 std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
179 filename);
180
181 HANDLE hFile = CreateFileA(dump_path.c_str(),
182 GENERIC_WRITE,
183 FILE_SHARE_WRITE,
184 NULL,
185 CREATE_ALWAYS,
186 FILE_ATTRIBUTE_NORMAL,
187 NULL);
188
189 if (hFile != INVALID_HANDLE_VALUE)
190 {
191 // Write the dump, ignoring the return value
192 f_mdwp(GetCurrentProcess(),
193 GetCurrentProcessId(),
194 hFile,
195 type,
196 ExInfop,
197 NULL,
198 NULL);
199
200 CloseHandle(hFile);
201 }
202
203 }
204}
205
206// static
207LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop)
208{
209
210 //
211 // Let go of a bunch of reserved memory to give library calls etc
212 // a chance to execute normally in the case that we ran out of
213 // memory.
214 //
215 gEmergencyMemoryReserve.release();
216
217 BOOL userWantsMaxiDump =
218 (stricmp(gSavedSettings.getString("LastName").c_str(), "linden") == 0)
219 || (stricmp(gSavedSettings.getString("LastName").c_str(), "tester") == 0);
220
221 BOOL alsoSaveMaxiDump = userWantsMaxiDump && !gInProductionGrid;
222
223 /* Calculate alsoSaveMaxiDump here */
224
225 if (exception_infop)
226 {
227 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
228
229 ExInfo.ThreadId = ::GetCurrentThreadId();
230 ExInfo.ExceptionPointers = exception_infop;
231 ExInfo.ClientPointers = NULL;
232
233 writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp");
234
235 if(alsoSaveMaxiDump)
236 writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp");
237 }
238 else
239 {
240 writeDumpToFile(MiniDumpNormal, NULL, "SecondLife.dmp");
241
242 if(alsoSaveMaxiDump)
243 writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), NULL, "SecondLifePlus.dmp");
244 }
245
246 if (!exception_infop)
247 {
248 // We're calling this due to a network error, not due to an actual exception.
249 // It doesn't realy matter what we return.
250 return EXCEPTION_CONTINUE_SEARCH;
251 }
252
253 //
254 // Call the newview crash callback, which will spawn the crash
255 // reporter. It may or may not spawn a dialog.
256 //
257 if (gCrashCallback)
258 {
259 gCrashCallback();
260 }
261
262 //
263 // At this point, we always want to exit the app. There's no graceful
264 // recovery for an unhandled exception.
265 //
266 // Just kill the process.
267 LONG retval = EXCEPTION_EXECUTE_HANDLER;
268
269 return retval;
270}
271
272#endif
273