SL-19744: Remove LLErrorThread and LLAppViewer::handleViewerCrash()
parent
1d1a63abe4
commit
27ee831e38
|
|
@ -39,7 +39,6 @@
|
|||
#include "llcommon.h"
|
||||
#include "llapr.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llerrorthread.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llmemory.h"
|
||||
|
|
@ -108,12 +107,7 @@ LLAppErrorHandler LLApp::sErrorHandler = NULL;
|
|||
BOOL LLApp::sErrorThreadRunning = FALSE;
|
||||
|
||||
|
||||
LLApp::LLApp() : mThreadErrorp(NULL)
|
||||
{
|
||||
commonCtor();
|
||||
}
|
||||
|
||||
void LLApp::commonCtor()
|
||||
LLApp::LLApp()
|
||||
{
|
||||
// Set our status to running
|
||||
setStatus(APP_STATUS_RUNNING);
|
||||
|
|
@ -143,12 +137,6 @@ void LLApp::commonCtor()
|
|||
mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
|
||||
}
|
||||
|
||||
LLApp::LLApp(LLErrorThread *error_thread) :
|
||||
mThreadErrorp(error_thread)
|
||||
{
|
||||
commonCtor();
|
||||
}
|
||||
|
||||
|
||||
LLApp::~LLApp()
|
||||
{
|
||||
|
|
@ -158,13 +146,6 @@ LLApp::~LLApp()
|
|||
mLiveFiles.clear();
|
||||
|
||||
setStopped();
|
||||
// HACK: wait for the error thread to clean itself
|
||||
ms_sleep(20);
|
||||
if (mThreadErrorp)
|
||||
{
|
||||
delete mThreadErrorp;
|
||||
mThreadErrorp = NULL;
|
||||
}
|
||||
|
||||
SUBSYSTEM_CLEANUP_DBG(LLCommon);
|
||||
}
|
||||
|
|
@ -401,21 +382,6 @@ void LLApp::setupErrorHandling(bool second_instance)
|
|||
#endif
|
||||
}
|
||||
|
||||
void LLApp::startErrorThread()
|
||||
{
|
||||
//
|
||||
// Start the error handling thread, which is responsible for taking action
|
||||
// when the app goes into the APP_STATUS_ERROR state
|
||||
//
|
||||
if(!mThreadErrorp)
|
||||
{
|
||||
LL_INFOS() << "Starting error thread" << LL_ENDL;
|
||||
mThreadErrorp = new LLErrorThread();
|
||||
mThreadErrorp->setUserData((void *) this);
|
||||
mThreadErrorp->start();
|
||||
}
|
||||
}
|
||||
|
||||
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
||||
{
|
||||
LLApp::sErrorHandler = handler;
|
||||
|
|
@ -476,7 +442,7 @@ void LLApp::setStatus(EAppStatus status)
|
|||
// static
|
||||
void LLApp::setError()
|
||||
{
|
||||
// set app status to ERROR so that the LLErrorThread notices
|
||||
// set app status to ERROR
|
||||
setStatus(APP_STATUS_ERROR);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <atomic>
|
||||
#include <chrono>
|
||||
// Forward declarations
|
||||
class LLErrorThread;
|
||||
class LLLiveFile;
|
||||
#if LL_LINUX
|
||||
#include <signal.h>
|
||||
|
|
@ -53,7 +52,6 @@ void clear_signals();
|
|||
|
||||
class LL_COMMON_API LLApp
|
||||
{
|
||||
friend class LLErrorThread;
|
||||
public:
|
||||
typedef enum e_app_status
|
||||
{
|
||||
|
|
@ -67,11 +65,6 @@ public:
|
|||
LLApp();
|
||||
virtual ~LLApp();
|
||||
|
||||
protected:
|
||||
LLApp(LLErrorThread* error_thread);
|
||||
void commonCtor();
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Return the static app instance if one was created.
|
||||
*/
|
||||
|
|
@ -257,14 +250,14 @@ public:
|
|||
void setupErrorHandling(bool mSecondInstance=false);
|
||||
|
||||
void setErrorHandler(LLAppErrorHandler handler);
|
||||
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
||||
static void runErrorHandler(); // run shortly after we detect an error
|
||||
//@}
|
||||
|
||||
|
||||
// the maximum length of the minidump filename returned by getMiniDumpFilename()
|
||||
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
|
||||
|
||||
// change the directory where Breakpad minidump files are written to
|
||||
void setDebugFileNames(const std::string &path);
|
||||
void setDebugFileNames(const std::string &path);
|
||||
|
||||
// Return the Google Breakpad minidump filename after a crash.
|
||||
char *getMiniDumpFilename() { return mMinidumpPath; }
|
||||
|
|
@ -324,9 +317,6 @@ private:
|
|||
typedef int(*signal_handler_func)(int signum);
|
||||
static LLAppErrorHandler sErrorHandler;
|
||||
|
||||
// Default application threads
|
||||
LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback
|
||||
|
||||
// This is the application level runnable scheduler.
|
||||
LLRunner mRunner;
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,6 @@ namespace LLError
|
|||
// used to indicate no class info known for logging
|
||||
|
||||
//LLCallStacks keeps track of call stacks and output the call stacks to log file
|
||||
//when LLAppViewer::handleViewerCrash() is triggered.
|
||||
//
|
||||
//Note: to be simple, efficient and necessary to keep track of correct call stacks,
|
||||
//LLCallStacks is designed not to be thread-safe.
|
||||
|
|
|
|||
|
|
@ -1,133 +0,0 @@
|
|||
/**
|
||||
* @file llerrorthread.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llerrorthread.h"
|
||||
|
||||
#include "llapp.h"
|
||||
#include "lltimer.h" // ms_sleep()
|
||||
|
||||
LLErrorThread::LLErrorThread()
|
||||
: LLThread("Error"),
|
||||
mUserDatap(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLErrorThread::~LLErrorThread()
|
||||
{
|
||||
}
|
||||
|
||||
void LLErrorThread::setUserData(void* user_data)
|
||||
{
|
||||
mUserDatap = user_data;
|
||||
}
|
||||
|
||||
|
||||
void* LLErrorThread::getUserData() const
|
||||
{
|
||||
return mUserDatap;
|
||||
}
|
||||
|
||||
#if !LL_WINDOWS
|
||||
//
|
||||
// Various signal/error handling functions that can't be put into the class
|
||||
//
|
||||
void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging)
|
||||
{
|
||||
exited = false;
|
||||
process_status = -1;
|
||||
// The child process exited. Call its callback, and then clean it up
|
||||
if (WIFEXITED(waitpid_status))
|
||||
{
|
||||
process_status = WEXITSTATUS(waitpid_status);
|
||||
exited = true;
|
||||
if (do_logging)
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child exited cleanly with return of " << process_status << LL_ENDL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (WIFSIGNALED(waitpid_status))
|
||||
{
|
||||
process_status = WTERMSIG(waitpid_status);
|
||||
exited = true;
|
||||
if (do_logging)
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child died because of uncaught signal " << process_status << LL_ENDL;
|
||||
#ifdef WCOREDUMP
|
||||
if (WCOREDUMP(waitpid_status))
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child dumped core" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child didn't dump core" << LL_ENDL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (do_logging)
|
||||
{
|
||||
// This is weird. I just dump the waitpid status into the status code,
|
||||
// not that there's any way of telling what it is...
|
||||
LL_INFOS() << "get_child_status - Got SIGCHILD but child didn't exit" << LL_ENDL;
|
||||
process_status = waitpid_status;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void LLErrorThread::run()
|
||||
{
|
||||
LLApp::sErrorThreadRunning = TRUE;
|
||||
// This thread sits and waits for the sole purpose
|
||||
// of waiting for the signal/exception handlers to flag the
|
||||
// application state as APP_STATUS_ERROR.
|
||||
LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL;
|
||||
|
||||
S32 counter = 0;
|
||||
while (! (LLApp::isError() || LLApp::isStopped()))
|
||||
{
|
||||
ms_sleep(10);
|
||||
counter++;
|
||||
}
|
||||
if (LLApp::isError())
|
||||
{
|
||||
// The app is in an error state, run the application's error handler.
|
||||
//LL_INFOS() << "thread_error - An error has occurred, running error callback!" << LL_ENDL;
|
||||
// Run the error handling callback
|
||||
LLApp::runErrorHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything is okay, a clean exit.
|
||||
//LL_INFOS() << "thread_error - Application exited cleanly" << LL_ENDL;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "thread_error - Exiting" << LL_ENDL;
|
||||
LLApp::sErrorThreadRunning = FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* @file llerrorthread.h
|
||||
* @brief Specialized thread to handle runtime errors.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLERRORTHREAD_H
|
||||
#define LL_LLERRORTHREAD_H
|
||||
|
||||
#include "llthread.h"
|
||||
|
||||
class LL_COMMON_API LLErrorThread : public LLThread
|
||||
{
|
||||
public:
|
||||
LLErrorThread();
|
||||
~LLErrorThread();
|
||||
|
||||
/*virtual*/ void run(void);
|
||||
void setUserData(void *user_data);
|
||||
void *getUserData() const;
|
||||
|
||||
protected:
|
||||
void* mUserDatap; // User data associated with this thread
|
||||
};
|
||||
|
||||
#endif // LL_LLERRORTHREAD_H
|
||||
|
|
@ -3582,8 +3582,6 @@ void LLAppViewer::writeSystemInfo()
|
|||
// "CrashNotHandled" is set here, while things are running well,
|
||||
// in case of a freeze. If there is a freeze, the crash logger will be launched
|
||||
// and can read this value from the debug_info.log.
|
||||
// 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);
|
||||
#else // LL_BUGSPLAT
|
||||
// "CrashNotHandled" is obsolete; it used (not very successsfully)
|
||||
|
|
@ -3675,163 +3673,6 @@ void getFileList()
|
|||
}
|
||||
#endif
|
||||
|
||||
void LLAppViewer::handleViewerCrash()
|
||||
{
|
||||
LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL;
|
||||
|
||||
LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ;
|
||||
|
||||
LLMemory::logMemoryInfo(true) ;
|
||||
|
||||
//print out recorded call stacks if there are any.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LLAppViewer* pApp = LLAppViewer::instance();
|
||||
if (pApp->beingDebugged())
|
||||
{
|
||||
// This will drop us into the debugger.
|
||||
abort();
|
||||
}
|
||||
|
||||
if (LLApp::isCrashloggerDisabled())
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Returns whether a dialog was shown.
|
||||
// Only do the logic in here once
|
||||
if (pApp->mReportedCrash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pApp->mReportedCrash = TRUE;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
||||
if ( parcel && parcel->getMusicURL()[0])
|
||||
{
|
||||
gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL();
|
||||
}
|
||||
if ( parcel && parcel->getMediaURL()[0])
|
||||
{
|
||||
gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL();
|
||||
}
|
||||
|
||||
gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
|
||||
gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = LLSD::Integer(LLMemory::getCurrentRSS() / 1024);
|
||||
|
||||
if(gLogoutInProgress)
|
||||
{
|
||||
gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
|
||||
}
|
||||
else
|
||||
{
|
||||
gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
|
||||
}
|
||||
|
||||
if(gAgent.getRegion())
|
||||
{
|
||||
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
|
||||
gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
|
||||
|
||||
const LLVector3& loc = gAgent.getPositionAgent();
|
||||
gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0];
|
||||
gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1];
|
||||
gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2];
|
||||
}
|
||||
|
||||
if(LLAppViewer::instance()->mMainloopTimeout)
|
||||
{
|
||||
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["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false);
|
||||
|
||||
//Write out the crash status file
|
||||
//Use marker file style setup, as that's the simplest, especially since
|
||||
//we're already in a crash situation
|
||||
if (gDirUtilp)
|
||||
{
|
||||
std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
gLLErrorActivated
|
||||
? LLERROR_MARKER_FILE_NAME
|
||||
: ERROR_MARKER_FILE_NAME);
|
||||
LLAPRFile crash_marker_file ;
|
||||
crash_marker_file.open(crash_marker_file_name, LL_APR_WB);
|
||||
if (crash_marker_file.getFileHandle())
|
||||
{
|
||||
LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL;
|
||||
recordMarkerVersion(crash_marker_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL;
|
||||
}
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
Sleep(200);
|
||||
#endif
|
||||
|
||||
char *minidump_file = pApp->getMiniDumpFilename();
|
||||
LL_DEBUGS("CRASHREPORT") << "minidump file name " << minidump_file << LL_ENDL;
|
||||
if(minidump_file && minidump_file[0] != 0)
|
||||
{
|
||||
gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LL_WINDOWS
|
||||
getFileList();
|
||||
#else
|
||||
LL_WARNS("CRASHREPORT") << "no minidump file?" << LL_ENDL;
|
||||
#endif
|
||||
}
|
||||
gDebugInfo["Dynamic"]["CrashType"]="crash";
|
||||
|
||||
if (gMessageSystem && gDirUtilp)
|
||||
{
|
||||
std::string filename;
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log");
|
||||
LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL;
|
||||
llofstream file(filename.c_str(), std::ios_base::binary);
|
||||
if(file.good())
|
||||
{
|
||||
gMessageSystem->summarizeLogs(file);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (gMessageSystem)
|
||||
{
|
||||
gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
|
||||
gMessageSystem->stopLogging();
|
||||
}
|
||||
|
||||
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
|
||||
|
||||
gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
|
||||
|
||||
// Close the debug file
|
||||
pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead.
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ public:
|
|||
|
||||
virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.
|
||||
// return false if the error trap needed restoration.
|
||||
static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon.
|
||||
void checkForCrash();
|
||||
|
||||
// Thread accessors
|
||||
|
|
|
|||
|
|
@ -80,8 +80,6 @@ int main( int argc, char **argv )
|
|||
|
||||
// install unexpected exception handler
|
||||
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
||||
// install crash handlers
|
||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
bool ok = viewer_app_ptr->init();
|
||||
if(!ok)
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ void constructViewer()
|
|||
}
|
||||
|
||||
gViewerAppPtr = new LLAppViewerMacOSX();
|
||||
|
||||
gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
}
|
||||
|
||||
bool initViewer()
|
||||
|
|
|
|||
|
|
@ -428,8 +428,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
|
|||
|
||||
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
||||
|
||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
// Set a debug info flag to indicate if multiple instances are running.
|
||||
bool found_other_instance = !create_app_mutex();
|
||||
gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance);
|
||||
|
|
|
|||
Loading…
Reference in New Issue