Breakpad3: WIP, minidump files created

TODO: re-work sending crash logs
get rid of standalone loggers
This commit is contained in:
Latif Khalifa
2013-10-01 13:43:45 +02:00
parent 6c45bf0353
commit c87f7b0576
29 changed files with 1745 additions and 1460 deletions

View File

@@ -558,6 +558,11 @@ LLAppViewer::LLAppViewer() :
llerrs << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << llendl;
}
mDumpPath ="";
// Need to do this initialization before we do anything else, since anything
// that touches files should really go through the lldir API
gDirUtilp->initAppDirs("SecondLife");
sInstance = this;
}
@@ -580,7 +585,9 @@ public:
};
bool LLAppViewer::init()
{
{
setupErrorHandling();
//
// Start of the application
//
@@ -605,9 +612,6 @@ bool LLAppViewer::init()
//initialize particle index pool
LLVOPartGroup::initClass();
// Need to do this initialization before we do anything else, since anything
// that touches files should really go through the lldir API
gDirUtilp->initAppDirs("SecondLife");
// set skin search path to default, will be overridden later
// this allows simple skinned file lookups to work
gDirUtilp->setSkinFolder("default");
@@ -636,6 +640,12 @@ bool LLAppViewer::init()
initMaxHeapSize() ;
LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ;
// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
mDumpPath = logdir;
setMiniDumpDir(logdir);
logdir += gDirUtilp->getDirDelimiter();
setDebugFileNames(logdir);
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
@@ -1448,6 +1458,14 @@ bool LLAppViewer::cleanup()
{
//ditch LLVOAvatarSelf instance
gAgentAvatarp = NULL;
// remove any old breakpad minidump files from the log directory
if (! isError())
{
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp");
}
cleanup_pose_stand();
//flag all elements as needing to be destroyed immediately
@@ -1725,6 +1743,7 @@ bool LLAppViewer::cleanup()
}
// </edit>
removeDumpDir();
writeDebugInfo();
if(!gDirUtilp->getLindenUserDir(true).empty())
@@ -2449,7 +2468,6 @@ bool LLAppViewer::initConfiguration()
initMarkerFile();
checkForCrash();
}
else
{
@@ -2469,10 +2487,6 @@ bool LLAppViewer::initConfiguration()
initMarkerFile();
if(!mSecondInstance)
{
checkForCrash();
}
}
// need to do this here - need to have initialized global settings first
@@ -2488,62 +2502,6 @@ bool LLAppViewer::initConfiguration()
return true; // Config was successful.
}
void LLAppViewer::checkForCrash(void)
{
#if LL_SEND_CRASH_REPORTS
// *NOTE:Mani The current state of the crash handler has the MacOSX
// sending all crash reports as freezes, in order to let
// the MacOSX CrashRepoter generate stacks before spawning the
// SL crash logger.
// The Linux and Windows clients generate their own stacks and
// spawn the SL crash logger immediately. This may change in the future.
#if LL_DARWIN
if(gLastExecEvent != LAST_EXEC_NORMAL)
#else
if (gLastExecEvent == LAST_EXEC_FROZE)
#endif
{
llinfos << "Last execution froze, requesting to send crash report." << llendl;
//
// Pop up a freeze or crash warning dialog
//
S32 choice;
const S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING);
if(cb == CRASH_BEHAVIOR_ASK)
{
std::ostringstream msg;
msg << LLTrans::getString("MBFrozenCrashed");
std::string alert = LLTrans::getString("APP_NAME") + " " + LLTrans::getString("MBAlert");
choice = OSMessageBox(msg.str(),
alert,
OSMB_YESNO);
}
else if(cb == CRASH_BEHAVIOR_NEVER_SEND)
{
choice = OSBTN_NO;
}
else
{
choice = OSBTN_YES;
}
if (OSBTN_YES == choice)
{
llinfos << "Sending crash report." << llendl;
bool report_freeze = true;
handleCrashReporting(report_freeze);
}
else
{
llinfos << "Not sending crash report." << llendl;
}
}
#endif // LL_SEND_CRASH_REPORTS
}
bool LLAppViewer::initWindow()
{
LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
@@ -2613,12 +2571,21 @@ bool LLAppViewer::initWindow()
return true;
}
void LLAppViewer::writeDebugInfo()
void LLAppViewer::writeDebugInfo(bool isStatic)
{
std::string debug_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log");
llinfos << "Opening debug file " << debug_filename << llendl;
llofstream out_file(debug_filename);
LLSDSerialize::toPrettyXML(gDebugInfo, out_file);
//Try to do the minimum when writing data during a crash.
std::string* debug_filename;
debug_filename = ( isStatic
? getStaticDebugFile()
: getDynamicDebugFile() );
llinfos << "Opening debug file " << *debug_filename << llendl;
llofstream out_file(*debug_filename);
isStatic ? LLSDSerialize::toPrettyXML(gDebugInfo, out_file)
: LLSDSerialize::toPrettyXML(gDebugInfo["Dynamic"], out_file);
out_file.close();
}
@@ -2669,6 +2636,10 @@ void LLAppViewer::removeCacheFiles(const std::string& file_mask)
void LLAppViewer::writeSystemInfo()
{
if (! gDebugInfo.has("Dynamic") )
gDebugInfo["Dynamic"] = LLSD::emptyMap();
gDebugInfo["SLLog"] = LLError::logFileName();
gDebugInfo["ClientInfo"]["Name"] = gVersionChannel;
@@ -2706,6 +2677,15 @@ void LLAppViewer::writeSystemInfo()
// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
// then the value of "CrashNotHandled" will be set to true.
gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
// Insert crash host url (url to post crash log to) if configured. This insures
// that the crash report will go to the proper location in the case of a
// prior freeze.
std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
if(crashHostUrl != "")
{
gDebugInfo["CrashHostUrl"] = crashHostUrl;
}
// Dump some debugging info
LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME")
@@ -2730,13 +2710,6 @@ void LLAppViewer::writeSystemInfo()
writeDebugInfo(); // Save out debug_info.log early, in case of crash.
}
void LLAppViewer::handleSyncViewerCrash()
{
LLAppViewer* pApp = LLAppViewer::instance();
// Call to pure virtual, handled by platform specific llappviewer instance.
pApp->handleSyncCrashTrace();
}
void LLAppViewer::handleViewerCrash()
{
llinfos << "Handle viewer crash entry." << llendl;
@@ -2768,8 +2741,12 @@ void LLAppViewer::handleViewerCrash()
}
pApp->mReportedCrash = TRUE;
// Make sure the watchdog gets turned off...
// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why.
// Insert crash host url (url to post crash log to) if configured.
std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
if(crashHostUrl != "")
{
gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl;
}
//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version
//to check against no matter what
@@ -2783,11 +2760,11 @@ void LLAppViewer::handleViewerCrash()
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if ( parcel && parcel->getMusicURL()[0])
{
gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL();
gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL();
}
if ( parcel && parcel->getMediaURL()[0])
{
gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL();
gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL();
}
@@ -2795,15 +2772,15 @@ void LLAppViewer::handleViewerCrash()
gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
if(gLogoutInProgress)
{
gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
}
else
{
@@ -2812,23 +2789,23 @@ void LLAppViewer::handleViewerCrash()
if(gAgent.getRegion())
{
gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
const LLVector3& loc = gAgent.getPositionAgent();
gDebugInfo["CurrentLocationX"] = loc.mV[0];
gDebugInfo["CurrentLocationY"] = loc.mV[1];
gDebugInfo["CurrentLocationZ"] = loc.mV[2];
gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0];
gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1];
gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2];
}
if(LLAppViewer::instance()->mMainloopTimeout)
{
gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
}
// The crash is being handled here so set this value to false.
// Otherwise the crash logger will think this crash was a freeze.
gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
//Write out the crash status file
//Use marker file style setup, as that's the simplest, especially since
@@ -2850,11 +2827,18 @@ void LLAppViewer::handleViewerCrash()
LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL;
}
}
char *minidump_file = pApp->getMiniDumpFilename();
if(minidump_file && minidump_file[0] != 0)
{
gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file;
}
gDebugInfo["Dynamic"]["CrashType"]="crash";
if (gMessageSystem && gDirUtilp)
{
std::string filename;
filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "stats.log");
filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log");
llofstream file(filename, llofstream::binary);
if(file.good())
{
@@ -2870,19 +2854,15 @@ void LLAppViewer::handleViewerCrash()
gMessageSystem->stopLogging();
}
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo);
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
// Close the debug file
pApp->writeDebugInfo();
pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead.
LLError::logToFile("");
// On Mac, we send the report on the next run, since we need macs crash report
// for a stack trace, so we have to let it the app fail.
#if !LL_DARWIN
// Remove the marker file, since otherwise we'll spawn a process that'll keep it locked
if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
if(gDebugInfo["Dynamic"]["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)
{
pApp->removeMarkerFile(true);
}
@@ -2891,11 +2871,6 @@ void LLAppViewer::handleViewerCrash()
pApp->removeMarkerFile(false);
}
// Call to pure virtual, handled by platform specific llappviewer instance.
pApp->handleCrashReporting();
#endif //!LL_DARWIN
return;
}
@@ -3020,6 +2995,18 @@ void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
LLAPRFile::remove( mLogoutMarkerFileName );
mLogoutMarkerFile = NULL;
}
else
{
LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
}
}
void LLAppViewer::removeDumpDir()
{
//Call this routine only on clean exit. Crash reporter will clean up
//its locking table for us.
std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
gDirUtilp->deleteDirAndContents(dump_dir);
}
void LLAppViewer::forceQuit()
@@ -3592,13 +3579,6 @@ void LLAppViewer::badNetworkHandler()
mPurgeOnExit = TRUE;
#if LL_WINDOWS
// Generates the minidump.
LLWinDebug::generateCrashStacks(NULL);
#endif
LLAppViewer::handleSyncViewerCrash();
LLAppViewer::handleViewerCrash();
std::string grid_support_msg = "";
if (!gHippoGridManager->getCurrentGrid()->getSupportUrl().empty())
{
@@ -3617,6 +3597,8 @@ void LLAppViewer::badNetworkHandler()
"If the problem continues, please report the issue at: \n"
"http://www.singularityviewer.org" << grid_support_msg;
forceDisconnect(message.str());
LLApp::instance()->writeMiniDump();
}
// This routine may get called more than once during the shutdown process.