SL-14961 Bugsplat logging

master
Andrey Kleshchev 2021-03-10 20:28:00 +02:00
parent 9505e14efe
commit 4076208a72
5 changed files with 103 additions and 6 deletions

View File

@ -5549,6 +5549,33 @@ void LLAppViewer::forceErrorDriverCrash()
glDeleteTextures(1, NULL);
}
void LLAppViewer::forceErrorCoroutineCrash()
{
LL_WARNS() << "Forcing a crash in LLCoros" << LL_ENDL;
LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw std::exception("A deliberate crash from LLCoros"); });
}
void LLAppViewer::forceErrorThreadCrash()
{
class LLCrashTestThread : public LLThread
{
public:
LLCrashTestThread() : LLThread("Crash logging test thread")
{
}
void run()
{
LL_ERRS() << "This is a deliberate llerror in thread" << LL_ENDL;
}
};
LL_WARNS() << "This is a deliberate crash in a thread" << LL_ENDL;
LLCrashTestThread *thread = new LLCrashTestThread();
thread->start();
}
void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
{
if(!mMainloopTimeout)

View File

@ -150,6 +150,8 @@ public:
virtual void forceErrorInfiniteLoop();
virtual void forceErrorSoftwareException();
virtual void forceErrorDriverCrash();
virtual void forceErrorCoroutineCrash();
virtual void forceErrorThreadCrash();
// The list is found in app_settings/settings_files.xml
// but since they are used explicitly in code,

View File

@ -609,6 +609,13 @@ bool LLAppViewerWin32::init()
#else // LL_BUGSPLAT
#pragma message("Building with BugSplat")
if (!isSecondInstance())
{
// Cleanup previous session
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
LLFile::remove(log_file, ENOENT);
}
std::string build_data_fname(
gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE
@ -616,7 +623,7 @@ bool LLAppViewerWin32::init()
llifstream inf(build_data_fname.c_str());
if (! inf.is_open())
{
LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname
<< "'" << LL_ENDL;
}
else
@ -626,7 +633,7 @@ bool LLAppViewerWin32::init()
if (! reader.parse(inf, build_data, false)) // don't collect comments
{
// gah, the typo is baked into Json::Reader API
LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname
<< "': " << reader.getFormatedErrorMessages() << LL_ENDL;
}
else
@ -634,7 +641,7 @@ bool LLAppViewerWin32::init()
Json::Value BugSplat_DB = build_data["BugSplat DB"];
if (! BugSplat_DB)
{
LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
<< build_data_fname << "'" << LL_ENDL;
}
else
@ -645,18 +652,35 @@ bool LLAppViewerWin32::init()
LL_VIEWER_VERSION_PATCH << '.' <<
LL_VIEWER_VERSION_BUILD));
DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting
MDSF_PREVENTHIJACKING; // disallow swiping Exception filter
bool needs_log_file = !isSecondInstance() && debugLoggingEnabled("BUGSPLAT");
if (needs_log_file)
{
// Startup only!
LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL;
dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE;
}
// have to convert normal wide strings to strings of __wchar_t
sBugSplatSender = new MiniDmpSender(
WCSTR(BugSplat_DB.asString()),
WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)),
WCSTR(version_string),
nullptr, // szAppIdentifier -- set later
MDSF_NONINTERACTIVE | // automatically submit report without prompting
MDSF_PREVENTHIJACKING); // disallow swiping Exception filter
dwFlags);
sBugSplatSender->setCallback(bugsplatSendLog);
if (needs_log_file)
{
// Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
sBugSplatSender->setLogFilePath(WCSTR(log_file));
}
// engage stringize() overload that converts from wstring
LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
LL_INFOS("BUGSPLAT") << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
<< ' ' << stringize(version_string) << ')' << LL_ENDL;
} // got BugSplat_DB
} // parsed build_data.json

View File

@ -286,6 +286,8 @@ void force_error_bad_memory_access(void *);
void force_error_infinite_loop(void *);
void force_error_software_exception(void *);
void force_error_driver_crash(void *);
void force_error_coroutine_crash(void *);
void force_error_thread_crash(void *);
void handle_force_delete(void*);
void print_object_info(void*);
@ -2363,6 +2365,24 @@ class LLAdvancedForceErrorDriverCrash : public view_listener_t
}
};
class LLAdvancedForceErrorCoroutineCrash : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
force_error_coroutine_crash(NULL);
return true;
}
};
class LLAdvancedForceErrorThreadCrash : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
force_error_thread_crash(NULL);
return true;
}
};
class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -8035,6 +8055,16 @@ void force_error_driver_crash(void *)
LLAppViewer::instance()->forceErrorDriverCrash();
}
void force_error_coroutine_crash(void *)
{
LLAppViewer::instance()->forceErrorCoroutineCrash();
}
void force_error_thread_crash(void *)
{
LLAppViewer::instance()->forceErrorThreadCrash();
}
class LLToolsUseSelectionForGrid : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -9202,6 +9232,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash");
view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash");
view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
// Advanced (toplevel)

View File

@ -2437,6 +2437,18 @@ function="World.EnvPreset"
<menu_item_call.on_click
function="Advanced.ForceErrorSoftwareException" />
</menu_item_call>
<menu_item_call
label="Force a Crash in a Coroutine"
name="Force a Crash in a Coroutine">
<menu_item_call.on_click
function="Advanced.ForceErrorCoroutineCrash" />
</menu_item_call>
<menu_item_call
label="Force a Crash in a Thread"
name="Force a Crash in a Thread">
<menu_item_call.on_click
function="Advanced.ForceErrorThreadCrash" />
</menu_item_call>
<menu_item_call
label="Force Disconnect Viewer"
name="Force Disconnect Viewer">