summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-03-10 20:28:00 +0200
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2021-03-12 00:25:53 +0200
commit4076208a72dbcb36adbdfcca86a9fbcc12d2bda3 (patch)
treee2a829944fbb0ee2c58b0bee05fc3e7113fb07a6 /indra/newview
parent9505e14efe65f426ebf4cf85ad4b876c20d0be64 (diff)
SL-14961 Bugsplat logging
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappviewer.cpp27
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llappviewerwin32.cpp36
-rw-r--r--indra/newview/llviewermenu.cpp32
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml12
5 files changed, 103 insertions, 6 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f518704e06..a1d73acfa5 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -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)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 5332fe2deb..6db45583eb 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -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,
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 9b1c0d1f8b..bb6156e209 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -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
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 29888fe9fd..2299f710f2 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -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)
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 5fa1847d1b..3ce55be554 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2438,6 +2438,18 @@ function="World.EnvPreset"
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">
<menu_item_call.on_click