summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappviewer.cpp89
-rw-r--r--indra/newview/llappviewer.h6
-rw-r--r--indra/newview/llappviewerwin32.cpp13
-rw-r--r--indra/newview/llstartup.cpp21
-rw-r--r--indra/newview/llviewerregion.cpp22
-rw-r--r--indra/newview/llviewerregion.h2
-rw-r--r--indra/newview/llwindebug.cpp441
-rw-r--r--indra/newview/llwindebug.h2
-rw-r--r--indra/newview/llworld.cpp10
-rw-r--r--indra/newview/llworld.h2
-rw-r--r--indra/newview/macutil_Prefix.h3
11 files changed, 420 insertions, 191 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c0e9833829..63d1986dec 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -106,6 +106,8 @@
#include "llcontainerview.h"
#include "llhoverview.h"
+#include "llsdserialize.h"
+
#if LL_WINDOWS && LL_LCD_COMPILE
#include "lllcd.h"
#endif
@@ -267,6 +269,8 @@ BOOL gAcceptCriticalMessage = FALSE;
LLUUID gViewerDigest; // MD5 digest of the viewer's executable file.
BOOL gLastExecFroze = FALSE;
+LLSD gDebugInfo;
+
U32 gFrameCount = 0;
U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground
LLPumpIO* gServicePump = NULL;
@@ -915,7 +919,6 @@ LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
LLAppViewer::LLAppViewer() :
mMarkerFile(NULL),
mLastExecFroze(false),
- mDebugFile(NULL),
mCrashBehavior(CRASH_BEHAVIOR_ASK),
mReportedCrash(false),
mNumSessions(0),
@@ -1220,7 +1223,7 @@ bool LLAppViewer::init()
CreateLCDDebugWindows();
#endif
- writeDebug(gGLManager.getGLInfoString());
+ gGLManager.getGLInfo(gDebugInfo);
llinfos << gGLManager.getGLInfoString() << llendl;
//load key settings
@@ -2351,30 +2354,13 @@ bool LLAppViewer::initWindow()
return true;
}
-void LLAppViewer::writeDebug(const char *str)
-{
- if (!mDebugFile)
- {
- std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
- llinfos << "Opening debug file " << debug_filename << llendl;
- mDebugFile = LLFile::fopen(debug_filename.c_str(), "w"); /* Flawfinder: ignore */
- if (!mDebugFile)
- {
- llinfos << "Opening debug file " << debug_filename << " failed. Using stderr." << llendl;
- mDebugFile = stderr;
- }
- }
- fputs(str, mDebugFile);
- fflush(mDebugFile);
-}
-
void LLAppViewer::closeDebug()
{
- if (mDebugFile)
- {
- fclose(mDebugFile);
- }
- mDebugFile = NULL;
+ std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
+ llinfos << "Opening debug file " << debug_filename << llendl;
+ std::ofstream out_file(debug_filename.c_str());
+ LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
+ out_file.close();
}
void LLAppViewer::cleanupSavedSettings()
@@ -2443,23 +2429,22 @@ void LLAppViewer::removeCacheFiles(const char* file_mask)
void LLAppViewer::writeSystemInfo()
{
- writeDebug("SL Log: ");
- writeDebug(LLError::logFileName());
- writeDebug("\n");
-
- std::string tmp_str = gSecondLife
- + llformat(" version %d.%d.%d build %d",
- LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, LL_VERSION_BUILD);
- writeDebug(tmp_str.c_str());
- writeDebug("\n");
- writeDebug(gSysCPU.getCPUString());
- writeDebug("\n");
+ gDebugInfo["SLLog"] = LLError::logFileName();
+
+ gDebugInfo["ClientInfo"]["Name"] = gSecondLife;
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
+ gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
+
+ gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily();
+ gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMhz();
+ gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec();
+ gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
+ gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
- tmp_str = llformat("RAM: %u KB\n", gSysMemory.getPhysicalMemoryKB());
- writeDebug(tmp_str.c_str());
- writeDebug("OS: ");
- writeDebug(getOSInfo().getOSString().c_str());
- writeDebug("\n");
+ gDebugInfo["RAMInfo"] = llformat("%u", gSysMemory.getPhysicalMemoryKB());
+ gDebugInfo["OSInfo"] = mSysOSInfo.getOSString().c_str();
// Dump some debugging info
llinfos << gSecondLife << " version "
@@ -2498,16 +2483,11 @@ void LLAppViewer::handleViewerCrash()
}
pApp->mReportedCrash = TRUE;
- BOOL do_crash_report = FALSE;
-
- do_crash_report = TRUE;
-
- pApp->writeDebug("Viewer exe: ");
- pApp->writeDebug(gDirUtilp->getExecutablePathAndName().c_str());
- pApp->writeDebug("\n");
- pApp->writeDebug("Cur path: ");
- pApp->writeDebug(gDirUtilp->getCurPath().c_str());
- pApp->writeDebug("\n\n");
+ gDebugInfo["SettingsFilename"] = gSettingsFileName;
+ gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
+ gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName().c_str();
+ gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath().c_str();
+ gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
if (gMessageSystem && gDirUtilp)
{
@@ -2517,27 +2497,24 @@ void LLAppViewer::handleViewerCrash()
if(file.good())
{
gMessageSystem->summarizeLogs(file);
+ file.close();
}
}
if (gMessageSystem)
{
- pApp->writeDebug(gMessageSystem->getCircuitInfoString());
+ gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
gMessageSystem->stopLogging();
}
- pApp->writeDebug("\n");
if (gWorldp)
{
- pApp->writeDebug(gWorldp->getInfoString());
+ gWorldp->getInfo(gDebugInfo);
}
// Close the debug file
pApp->closeDebug();
LLError::logToFile("");
- // Close the SecondLife.log
- //pApp->removeMarkerFile();
-
// Call to pure virtual, handled by platform specifc llappviewer instance.
pApp->handleCrashReporting();
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 227a27a8ac..e97aead955 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -68,9 +68,6 @@ public:
// This version stores the argc and argv for later usage, make sure the params passed in last as long as this class.
bool tempStoreCommandOptions(int argc, char** argv);
- // write string to "debug_info.log", used for crash reporting.
- void writeDebug(const char *str);
- void writeDebug(const std::string& str) { writeDebug(str.c_str()); };
void closeDebug();
const LLOSInfo& getOSInfo() const { return mSysOSInfo; }
@@ -165,8 +162,6 @@ private:
FILE *mMarkerFile; // A file created to indicate the app is running.
bool mLastExecFroze; // Set on init if the marker file was found.
- FILE* mDebugFile; // output stream written to via writeDebug()
-
LLOSInfo mSysOSInfo;
S32 mCrashBehavior;
bool mReportedCrash;
@@ -202,6 +197,7 @@ extern BOOL gProbeHardware;
extern LLString gDisabledMessage; // llstartup
extern BOOL gHideLinks; // used by llpanellogin, lllfloaterbuycurrency, llstartup
extern BOOL gInProductionGrid;
+extern LLSD gDebugInfo;
extern BOOL gAllowIdleAFK;
extern F32 gAFKTimeout;
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 1d7a6690fc..814c209e67 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -322,9 +322,16 @@ bool LLAppViewerWin32::initWindow()
return LLAppViewer::initWindow();
}
-void write_debug_callback(const char* str)
+void write_debug_dx(const char* str)
{
- LLAppViewer::instance()->writeDebug(str);
+ LLString value = gDebugInfo["DXInfo"].asString();
+ value += str;
+ gDebugInfo["DXInfo"] = value;
+}
+
+void write_debug_dx(const std::string& str)
+{
+ write_debug_dx(str.c_str());
}
bool LLAppViewerWin32::initHardwareTest()
@@ -340,7 +347,7 @@ bool LLAppViewerWin32::initHardwareTest()
LLSplashScreen::update("Detecting hardware...");
llinfos << "Attempting to poll DirectX for hardware info" << llendl;
- gDXHardware.setWriteDebugFunc(write_debug_callback);
+ gDXHardware.setWriteDebugFunc(write_debug_dx);
BOOL probe_ok = gDXHardware.getInfo(vram_only);
if (!probe_ok
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index c43c4e8685..dda155d0df 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -773,12 +773,11 @@ BOOL idle_startup()
gSavedSettings.setString("FirstName", firstname);
gSavedSettings.setString("LastName", lastname);
+
+
+
llinfos << "Attempting login as: " << firstname << " " << lastname << llendl;
- LLAppViewer::instance()->writeDebug("Attempting login as: ");
- LLAppViewer::instance()->writeDebug(firstname);
- LLAppViewer::instance()->writeDebug(" ");
- LLAppViewer::instance()->writeDebug(lastname);
- LLAppViewer::instance()->writeDebug("\n");
+ gDebugInfo["LoginName"] = firstname + " " + lastname;
}
// create necessary directories
@@ -826,6 +825,7 @@ BOOL idle_startup()
LLPanelLogin::close();
}
+
//For HTML parsing in text boxes.
LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") );
LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &LLURLDispatcher::dispatch, &LLURLDispatcher::dispatch );
@@ -895,6 +895,8 @@ BOOL idle_startup()
if(STATE_LOGIN_AUTH_INIT == LLStartUp::getStartupState())
{
//#define LL_MINIMIAL_REQUESTED_OPTIONS
+ gDebugInfo["GridUtilHost"] = gGridInfo[gGridChoice].mName;
+
lldebugs << "STATE_LOGIN_AUTH_INIT" << llendl;
if (!gUserAuthp)
{
@@ -932,6 +934,7 @@ BOOL idle_startup()
}
LLAppViewer::instance()->getLoginURIs();
sAuthUris = LLAppViewer::instance()->getLoginURIs();
+
sAuthUriNum = 0;
auth_method = "login_to_simulator";
auth_desc = "Logging in. ";
@@ -1226,15 +1229,11 @@ BOOL idle_startup()
const char* text;
text = gUserAuthp->getResponse("agent_id");
if(text) gAgentID.set(text);
- LLAppViewer::instance()->writeDebug("AgentID: ");
- LLAppViewer::instance()->writeDebug(text);
- LLAppViewer::instance()->writeDebug("\n");
+ gDebugInfo["AgentID"] = text;
text = gUserAuthp->getResponse("session_id");
if(text) gAgentSessionID.set(text);
- LLAppViewer::instance()->writeDebug("SessionID: ");
- LLAppViewer::instance()->writeDebug(text);
- LLAppViewer::instance()->writeDebug("\n");
+ gDebugInfo["SessionID"] = text;
text = gUserAuthp->getResponse("secure_session_id");
if(text) gAgent.mSecureSessionID.set(text);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 95a1db12df..5bfe023168 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -964,28 +964,16 @@ void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg)
}
}
-LLString LLViewerRegion::getInfoString()
+void LLViewerRegion::getInfo(LLSD& info)
{
- char tmp_buf[256]; /* Flawfinder: ignore */
- LLString info;
-
- info = "Region: ";
- getHost().getString(tmp_buf, 256);
- info += tmp_buf;
- info += ":";
- info += getName();
- info += "\n";
-
+ info["Region"]["Host"] = getHost().getIPandPort();
+ info["Region"]["Name"] = getName();
U32 x, y;
from_region_handle(getHandle(), &x, &y);
- snprintf(tmp_buf, sizeof(tmp_buf), "%d:%d", x, y); /* Flawfinder: ignore */
- info += "Handle:";
- info += tmp_buf;
- info += "\n";
- return info;
+ info["Region"]["Handle"]["x"] = (LLSD::Integer)x;
+ info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
-
void LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
{
U32 local_id = objectp->getLocalID();
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 013a96f2d1..a0953e561e 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -223,7 +223,7 @@ public:
F32 getLandHeightRegion(const LLVector3& region_pos);
- LLString getInfoString();
+ void getInfo(LLSD& info);
// handle a full update message
void cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp
index 88ba5822eb..13c5ac3bbb 100644
--- a/indra/newview/llwindebug.cpp
+++ b/indra/newview/llwindebug.cpp
@@ -33,12 +33,70 @@
#ifdef LL_WINDOWS
+#include <tchar.h>
+#include <tlhelp32.h>
+#include <atlbase.h>
+#include "llappviewer.h"
#include "llwindebug.h"
#include "llviewercontrol.h"
#include "lldir.h"
-
-#include "llappviewer.h"
-
+#include "llsd.h"
+#include "llsdserialize.h"
+
+#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union
+#pragma warning(disable: 4100) //unreferenced formal parameter
+
+/*
+LLSD Block for Windows Dump Information
+<llsd>
+ <map>
+ <key>Platform</key>
+ <string></string>
+ <key>Process</key>
+ <string></string>
+ <key>Module</key>
+ <string></string>
+ <key>Date Modified</key>
+ <string></string>
+ <key>Exception Code</key>
+ <string></string>
+ <key>Exception Read/Write Address</key>
+ <string></string>
+ <key>Instruction</key>
+ <string></string>
+ <key>Registers</key>
+ <map>
+ <!-- Continued for all registers -->
+ <key>EIP</key>
+ <string>...</string>
+ <!-- ... -->
+ </map>
+ <key>Call Stack</key>
+ <array>
+ <!-- One map per stack frame -->
+ <map>
+ <key>Module Name</key>
+ <string></string>
+ <key>Module Base Address</key>
+ <string></string>
+ <key>Module Offset Address</key>
+ <string></string>
+ <key>Parameters</key>
+ <array>
+ <string></string>
+ </array>
+ </map>
+ <!-- ... -->
+ </array>
+ </map>
+</llsd>
+
+*/
+
+// From viewer.h
+extern BOOL gInProductionGrid;
+
+extern void (*gCrashCallback)(void);
// based on dbghelp.h
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
@@ -49,6 +107,255 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hF
MINIDUMPWRITEDUMP f_mdwp = NULL;
+#undef UNICODE
+
+HMODULE hDbgHelp;
+
+// Tool Help functions.
+typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
+typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
+typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
+
+CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_;
+MODULE32_FIRST Module32First_;
+MODULE32_NEST Module32Next_;
+
+#define DUMP_SIZE_MAX 8000 //max size of our dump
+#define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls
+#define NL L"\r\n" //new line
+
+//****************************************************************************************
+BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr)
+//****************************************************************************************
+// Find module by Ret_Addr (address in the module).
+// Return Module_Name (full path) and Module_Addr (start address).
+// Return TRUE if found.
+{
+ MODULEENTRY32 M = {sizeof(M)};
+ HANDLE hSnapshot;
+
+ bool found = false;
+
+ if (CreateToolhelp32Snapshot_)
+ {
+ hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0);
+
+ if ((hSnapshot != INVALID_HANDLE_VALUE) &&
+ Module32First_(hSnapshot, &M))
+ {
+ do
+ {
+ if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize)
+ {
+ lstrcpyn(Module_Name, M.szExePath, MAX_PATH);
+ Module_Addr = M.modBaseAddr;
+ found = true;
+ break;
+ }
+ } while (Module32Next_(hSnapshot, &M));
+ }
+
+ CloseHandle(hSnapshot);
+ }
+
+ return found;
+} //Get_Module_By_Ret_Addr
+
+//******************************************************************
+void WINAPI Get_Call_Stack(PEXCEPTION_POINTERS pException, LLSD& info)
+//******************************************************************
+// Fill Str with call stack info.
+// pException can be either GetExceptionInformation() or NULL.
+// If pException = NULL - get current call stack.
+{
+
+ USES_CONVERSION;
+
+ LPWSTR Module_Name = new WCHAR[MAX_PATH];
+ PBYTE Module_Addr = 0;
+
+ typedef struct STACK
+ {
+ STACK * Ebp;
+ PBYTE Ret_Addr;
+ DWORD Param[0];
+ } STACK, * PSTACK;
+
+ STACK Stack = {0, 0};
+ PSTACK Ebp;
+
+ if (pException) //fake frame for exception address
+ {
+ Stack.Ebp = (PSTACK)pException->ContextRecord->Ebp;
+ Stack.Ret_Addr = (PBYTE)pException->ExceptionRecord->ExceptionAddress;
+ Ebp = &Stack;
+ }
+ else
+ {
+ Ebp = (PSTACK)&pException - 1; //frame addr of Get_Call_Stack()
+
+ // Skip frame of Get_Call_Stack().
+ if (!IsBadReadPtr(Ebp, sizeof(PSTACK)))
+ Ebp = Ebp->Ebp; //caller ebp
+ }
+
+ // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX.
+ // Break trace on wrong stack frame.
+ for (int Ret_Addr_I = 0, i = 0;
+ (Ret_Addr_I < CALL_TRACE_MAX) && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr));
+ Ret_Addr_I++, Ebp = Ebp->Ebp, ++i)
+ {
+ // If module with Ebp->Ret_Addr found.
+
+ if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr))
+ {
+ // Save module's address and full path.
+ info["Call Stack"][i]["Module Name"] = W2A(Module_Name);
+ info["Call Stack"][i]["Module Address"] = (int)Module_Addr;
+ info["Call Stack"][i]["Call Offset"] = (int)(Ebp->Ret_Addr - Module_Addr);
+
+ LLSD params;
+ // Save 5 params of the call. We don't know the real number of params.
+ if (pException && !Ret_Addr_I) //fake frame for exception address
+ params[0] = "Exception Offset";
+ else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD)))
+ {
+ for(int j = 0; j < 5; ++j)
+ {
+ params[j] = (int)Ebp->Param[j];
+ }
+ }
+ info["Call Stack"][i]["Parameters"] = params;
+ }
+ info["Call Stack"][i]["Return Address"] = (int)Ebp->Ret_Addr;
+ }
+} //Get_Call_Stack
+
+//***********************************
+void WINAPI Get_Version_Str(LLSD& info)
+//***********************************
+// Fill Str with Windows version.
+{
+ OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later
+
+ if (!GetVersionEx((POSVERSIONINFO)&V))
+ {
+ ZeroMemory(&V, sizeof(V));
+ V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx((POSVERSIONINFO)&V);
+ }
+
+ if (V.dwPlatformId != VER_PLATFORM_WIN32_NT)
+ V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx
+
+ info["Platform"] = llformat("Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,...
+ V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType);
+} //Get_Version_Str
+
+//*************************************************************
+LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException)
+//*************************************************************
+// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str.
+{
+ USES_CONVERSION;
+
+ LLSD info;
+ LPWSTR Str;
+ int Str_Len;
+ int i;
+ LPWSTR Module_Name = new WCHAR[MAX_PATH];
+ PBYTE Module_Addr;
+ HANDLE hFile;
+ FILETIME Last_Write_Time;
+ FILETIME Local_File_Time;
+ SYSTEMTIME T;
+
+ Str = new WCHAR[DUMP_SIZE_MAX];
+ Str_Len = 0;
+ if (!Str)
+ return NULL;
+
+ Get_Version_Str(info);
+
+
+ GetModuleFileName(NULL, Str, MAX_PATH);
+ info["Process"] = W2A(Str);
+
+ // If exception occurred.
+ if (pException)
+ {
+ EXCEPTION_RECORD & E = *pException->ExceptionRecord;
+ CONTEXT & C = *pException->ContextRecord;
+
+ // If module with E.ExceptionAddress found - save its path and date.
+ if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr))
+ {
+ info["Module"] = W2A(Module_Name);
+
+ if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
+ {
+ if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time))
+ {
+ FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time);
+ FileTimeToSystemTime(&Local_File_Time, &T);
+
+ info["Date Modified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear);
+ }
+ CloseHandle(hFile);
+ }
+ }
+ else
+ {
+ info["Exception Addr"] = (int)E.ExceptionAddress;
+ }
+
+ info["Exception Code"] = (int)E.ExceptionCode;
+
+ /*
+ //TODO: Fix this
+ if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
+ {
+ // Access violation type - Write/Read.
+ LLSD exception_info;
+ exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read";
+ exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]);
+ info["Exception Information"] = exception_info;
+ }
+ */
+
+
+ // Save instruction that caused exception.
+ Str_Len = 0;
+ for (i = 0; i < 16; i++)
+ Str_Len += wsprintf(Str + Str_Len, L" %02X", PBYTE(E.ExceptionAddress)[i]);
+ info["Instruction"] = W2A(Str);
+
+ LLSD registers;
+ registers["EAX"] = (int)C.Eax;
+ registers["EBX"] = (int)C.Ebx;
+ registers["ECX"] = (int)C.Ecx;
+ registers["EDX"] = (int)C.Edx;
+ registers["ESI"] = (int)C.Esi;
+ registers["EDI"] = (int)C.Edi;
+ registers["ESP"] = (int)C.Esp;
+ registers["EBP"] = (int)C.Ebp;
+ registers["EIP"] = (int)C.Eip;
+ registers["EFlags"] = (int)C.EFlags;
+ info["Registers"] = registers;
+ } //if (pException)
+
+ // Save call stack info.
+ Get_Call_Stack(pException, info);
+
+ if (Str[0] == NL[0])
+ lstrcpy(Str, Str + sizeof(NL) - 1);
+
+
+ return info;
+} //Get_Exception_Info
+
+#define UNICODE
class LLMemoryReserve {
@@ -92,7 +399,6 @@ static LLMemoryReserve gEmergencyMemoryReserve;
// static
BOOL LLWinDebug::setupExceptionHandler()
{
-#ifdef LL_RELEASE_FOR_DOWNLOAD
static BOOL s_first_run = TRUE;
// Load the dbghelp dll now, instead of waiting for the crash.
@@ -119,7 +425,7 @@ BOOL LLWinDebug::setupExceptionHandler()
msg += local_dll_name;
msg += "!\n";
- LLAppViewer::instance()->writeDebug(msg.c_str());
+ //write_debug(msg.c_str());
ok = FALSE;
}
@@ -129,7 +435,7 @@ BOOL LLWinDebug::setupExceptionHandler()
if (!f_mdwp)
{
- LLAppViewer::instance()->writeDebug("No MiniDumpWriteDump!\n");
+ //write_debug("No MiniDumpWriteDump!\n");
FreeLibrary(hDll);
hDll = NULL;
ok = FALSE;
@@ -139,76 +445,37 @@ BOOL LLWinDebug::setupExceptionHandler()
gEmergencyMemoryReserve.reserve();
}
- // *REMOVE: LLApp now handles the exception handing.
- // LLAppViewerWin32 calls SetUnhandledExceptionFilter()
-
- //LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
- //prev_filter = SetUnhandledExceptionFilter(LLWinDebug::handleException);
-
- //if (s_first_run)
- //{
- // // We're fine, this is the first run.
- // s_first_run = FALSE;
- // return ok;
- //}
- //if (!prev_filter)
- //{
- // llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl;
- // ok = FALSE;
- //}
- //if (prev_filter != LLWinDebug::handleException)
- //{
- // llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl;
- // ok = FALSE;
- //}
+ LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
+ prev_filter = SetUnhandledExceptionFilter(LLWinDebug::handleException);
- return ok;
-#else
- // Internal builds don't mess with exception handling.
- return TRUE;
-#endif
-}
+ // 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");
-void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename)
-{
- if(f_mdwp == NULL)
+ if (s_first_run)
{
- LLAppViewer::instance()->writeDebug("No way to generate a minidump, no MiniDumpWriteDump function!\n");
+ // We're fine, this is the first run.
+ s_first_run = FALSE;
+ return ok;
}
- else if(gDirUtilp == NULL)
+ if (!prev_filter)
{
- LLAppViewer::instance()->writeDebug("No way to generate a minidump, no gDirUtilp!\n");
+ llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl;
+ ok = FALSE;
}
- else
+ if (prev_filter != LLWinDebug::handleException)
{
- std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
- filename);
-
- HANDLE hFile = CreateFileA(dump_path.c_str(),
- GENERIC_WRITE,
- FILE_SHARE_WRITE,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- if (hFile != INVALID_HANDLE_VALUE)
- {
- // Write the dump, ignoring the return value
- f_mdwp(GetCurrentProcess(),
- GetCurrentProcessId(),
- hFile,
- type,
- ExInfop,
- NULL,
- NULL);
-
- CloseHandle(hFile);
- }
-
+ llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl;
+ ok = FALSE;
}
-}
+ return ok;
+ // Internal builds don't mess with exception handling.
+ //return TRUE;
+}
// static
LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop)
{
@@ -222,42 +489,35 @@ LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop)
//
gEmergencyMemoryReserve.release();
- BOOL userWantsMaxiDump =
- (stricmp(gSavedSettings.getString("LastName").c_str(), "linden") == 0)
- || (stricmp(gSavedSettings.getString("LastName").c_str(), "tester") == 0);
-
- BOOL alsoSaveMaxiDump = userWantsMaxiDump && !gInProductionGrid;
-
- /* Calculate alsoSaveMaxiDump here */
-
if (exception_infop)
{
- _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
- ExInfo.ThreadId = ::GetCurrentThreadId();
- ExInfo.ExceptionPointers = exception_infop;
- ExInfo.ClientPointers = NULL;
+ std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+ "SecondLifeException");
- writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp");
+ std::string log_path = dump_path + ".log";
- if(alsoSaveMaxiDump)
- writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp");
+ LLSD info;
+ info = Get_Exception_Info(exception_infop);
+ if (info)
+ {
+ std::ofstream out_file(log_path.c_str());
+ LLSDSerialize::toPrettyXML(info, out_file);
+ out_file.close();
+ }
}
else
{
- writeDumpToFile(MiniDumpNormal, NULL, "SecondLife.dmp");
-
- if(alsoSaveMaxiDump)
- writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), NULL, "SecondLifePlus.dmp");
- }
-
- if (!exception_infop)
- {
// We're calling this due to a network error, not due to an actual exception.
// It doesn't realy matter what we return.
return EXCEPTION_CONTINUE_SEARCH;
}
+ //handle viewer crash must be called here since
+ //we don't return handling of the application
+ //back to the process.
+ LLAppViewer::handleViewerCrash();
+
//
// At this point, we always want to exit the app. There's no graceful
// recovery for an unhandled exception.
@@ -269,4 +529,3 @@ LONG LLWinDebug::handleException(struct _EXCEPTION_POINTERS *exception_infop)
}
#endif
-
diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h
index bb1f11df67..e420138216 100644
--- a/indra/newview/llwindebug.h
+++ b/indra/newview/llwindebug.h
@@ -41,7 +41,7 @@ public:
static BOOL setupExceptionHandler();
static LONG WINAPI handleException(struct _EXCEPTION_POINTERS *pExceptionInfo);
- static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename);
+ //static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const char *filename);
};
#endif // LL_LLWINDEBUG_H
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 36be05fe7f..e76123557c 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -972,16 +972,16 @@ void LLWorld::requestCacheMisses()
}
}
-LLString LLWorld::getInfoString()
+void LLWorld::getInfo(LLSD& info)
{
- LLString info_string("World Info:\n");
+ LLSD region_info;
for (region_list_t::iterator iter = mRegionList.begin();
iter != mRegionList.end(); ++iter)
- {
+ {
LLViewerRegion* regionp = *iter;
- info_string += regionp->getInfoString();
+ regionp->getInfo(region_info);
+ info["World"].append(region_info);
}
- return info_string;
}
void LLWorld::disconnectRegions()
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 91685cd297..e634459acd 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -142,7 +142,7 @@ public:
void setSpaceTimeUSec(const U64 space_time_usec);
U64 getSpaceTimeUSec() const;
- LLString getInfoString();
+ void getInfo(LLSD& info);
public:
typedef std::list<LLViewerRegion*> region_list_t;
diff --git a/indra/newview/macutil_Prefix.h b/indra/newview/macutil_Prefix.h
index f8050c8d35..145a01c702 100644
--- a/indra/newview/macutil_Prefix.h
+++ b/indra/newview/macutil_Prefix.h
@@ -39,3 +39,6 @@
#include <Carbon/Carbon.h>
+#undef check
+#undef verify
+#undef require