From 803b75a718833ccf236f00b425faff4eaf0f29cb Mon Sep 17 00:00:00 2001 From: callum_linden Date: Wed, 18 Oct 2017 18:36:10 -0700 Subject: First version that builds with a dummy BugSplay call in llapp.cpp --- indra/llcommon/CMakeLists.txt | 3 +++ indra/llcommon/llapp.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d9eb13d65a..50e262ae7a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,6 +13,7 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) +include(BUGSPLAT) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -21,6 +22,7 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ${URIPARSER_INCLUDE_DIRS} + ${BUGSPLAT_INCLUDE_DIR} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -291,6 +293,7 @@ target_link_libraries( ${BOOST_SYSTEM_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} ${URIPARSER_LIBRARIES} + ${BUGSPLAT_LIBRARIES} ) if (DARWIN) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6cc9e804d4..9dd9fc3c70 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -50,6 +50,10 @@ #include "stringize.h" #include "llcleanup.h" +#include "BugSplat.h" + +MiniDmpSender *mpSender; + // // Signal handling // @@ -151,6 +155,14 @@ void LLApp::commonCtor() // (this is used to avoid allocating memory in the crash handler) memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; + + + static const wchar_t *bugdb_name = L"second_life_callum_test"; + static const wchar_t *app_name = L"SecondLifeViewer"; + static const wchar_t *app_version = L"1.0.0"; + mpSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + } LLApp::LLApp(LLErrorThread *error_thread) : -- cgit v1.3 From e75b16f3584b76df706a470395383abf680eb87f Mon Sep 17 00:00:00 2001 From: callum_linden Date: Thu, 19 Oct 2017 11:34:36 -0700 Subject: First pass at adding BugSplat code to viewer and turning off existing (Google Breakpad) exception handling --- indra/llcommon/llapp.cpp | 76 +++++++++++++++++++++++++++++++++++++++--------- indra/llcommon/llapp.h | 10 ++++++- 2 files changed, 72 insertions(+), 14 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9dd9fc3c70..ea4a0fb59c 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -49,10 +49,20 @@ #include "google_breakpad/exception_handler.h" #include "stringize.h" #include "llcleanup.h" - #include "BugSplat.h" -MiniDmpSender *mpSender; +// TESTING ONLY - REMOVE FOR PRODUCTION +// (Want to only invoke BugSplat crash reporting in the same way we did for Breakpad - for Release viewers +// but need to test here in a ReleaseWithDebugInfo environment) +#if BUGSPLAT_ENABLED +#define LL_SEND_CRASH_REPORTS 1 +#endif + +// BugSplat crash reporting tool - http://bugsplat.com +#if BUGSPLAT_ENABLED +bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2); +MiniDmpSender *gBugSplatSender; +#endif // // Signal handling @@ -155,14 +165,6 @@ void LLApp::commonCtor() // (this is used to avoid allocating memory in the crash handler) memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH); mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; - - - static const wchar_t *bugdb_name = L"second_life_callum_test"; - static const wchar_t *app_name = L"SecondLifeViewer"; - static const wchar_t *app_version = L"1.0.0"; - mpSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); - - } LLApp::LLApp(LLErrorThread *error_thread) : @@ -397,6 +399,42 @@ void EnableCrashingOnCrashes() } #endif +#if BUGSPLAT_ENABLED +bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) +{ + switch (nCode) + { + case MDSCB_EXCEPTIONCODE: + { + EXCEPTION_RECORD *p = (EXCEPTION_RECORD *)lpVal1; + DWORD code = p ? p->ExceptionCode : 0; + + // create some files in the %temp% directory and attach them + wchar_t cmdString[2 * MAX_PATH]; + wchar_t filePath[MAX_PATH]; + wchar_t tempPath[MAX_PATH]; + GetTempPathW(MAX_PATH, tempPath); + + wsprintf(filePath, L"%sfile1.txt", tempPath); + wsprintf(cmdString, L"echo Exception Code = 0x%08x > %s", code, filePath); + _wsystem(cmdString); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + + wsprintf(filePath, L"%sfile2.txt", tempPath); + wchar_t buf[_MAX_PATH]; + gBugSplatSender->getMinidumpPath((__wchar_t *)buf, _MAX_PATH); + + wsprintf(cmdString, L"echo Crash reporting is so clutch! minidump path = %s > %s", buf, filePath); + _wsystem(cmdString); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + } + break; + } + + return false; +} +#endif + void LLApp::setupErrorHandling(bool second_instance) { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -405,6 +443,17 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS #if LL_SEND_CRASH_REPORTS + +#if BUGSPLAT_ENABLED + // TODOCP: populate these fields correctly + static const wchar_t *bugdb_name = L"second_life_callum_test"; + static const wchar_t *app_name = L"SecondLifeViewer"; + static const wchar_t *app_version = L"1.0.0"; + gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + gBugSplatSender->setCallback(BugSplatExceptionCallback); +#else + EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -466,8 +515,9 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif -#else +#endif // BUGSPLAT_ENABLED +#endif // LL_SEND_CRASH_REPORTS +#else // not LL_WINDOWS // // Start up signal handling. // @@ -528,7 +578,7 @@ void LLApp::setupErrorHandling(bool second_instance) } #endif -#endif +#endif // LL_WINDOWS startErrorThread(); } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index acd829d864..5a4b7f13df 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -30,6 +30,7 @@ #include #include "llrun.h" #include "llsd.h" + // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -39,6 +40,14 @@ class LLLiveFile; #include #endif +// first version of Bugsplat (http://bugsplat.com) crash reporting tool +// is only supported on Windows - macOS to follow. +#define BUGSPLAT_ENABLED LL_WINDOWS + +#if BUGSPLAT_ENABLED +class __declspec(dllexport) MiniDmpSender; +#endif + typedef void (*LLAppErrorHandler)(); #if !LL_WINDOWS @@ -316,7 +325,6 @@ private: google_breakpad::ExceptionHandler * mExceptionHandler; - #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); #endif -- cgit v1.3 From d359dca06518d778c0f115afec8c759ca026de47 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Oct 2017 14:28:43 -0700 Subject: painfully add in the path to the second life log file that we also send - painful because of string <--> wstring issues --- indra/llcommon/llapp.cpp | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index ea4a0fb59c..6ea1700ea8 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -406,27 +406,11 @@ bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) { case MDSCB_EXCEPTIONCODE: { - EXCEPTION_RECORD *p = (EXCEPTION_RECORD *)lpVal1; - DWORD code = p ? p->ExceptionCode : 0; - - // create some files in the %temp% directory and attach them - wchar_t cmdString[2 * MAX_PATH]; - wchar_t filePath[MAX_PATH]; - wchar_t tempPath[MAX_PATH]; - GetTempPathW(MAX_PATH, tempPath); - - wsprintf(filePath, L"%sfile1.txt", tempPath); - wsprintf(cmdString, L"echo Exception Code = 0x%08x > %s", code, filePath); - _wsystem(cmdString); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); - - wsprintf(filePath, L"%sfile2.txt", tempPath); - wchar_t buf[_MAX_PATH]; - gBugSplatSender->getMinidumpPath((__wchar_t *)buf, _MAX_PATH); - - wsprintf(cmdString, L"echo Crash reporting is so clutch! minidump path = %s > %s", buf, filePath); - _wsystem(cmdString); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)filePath); + // send the main viewer log file (Clearly a temporary hack since we don't have access to the gDir*** set of functions in newview + const std::string appdata = std::string(getenv("APPDATA")); + const std::string logfile = appdata + "\\SecondLife\\logs\\Secondlife.log"; + const std::wstring wide_logfile(logfile.begin(), logfile.end()); + gBugSplatSender->sendAdditionalFile((const __wchar_t *)wide_logfile.c_str()); } break; } -- cgit v1.3 From 2e3c5ac88a434ee437bc3e68b321d5bd0bcd7cc9 Mon Sep 17 00:00:00 2001 From: callum_linden Date: Tue, 24 Oct 2017 16:13:23 -0700 Subject: Add in real SL viewer name and version --- indra/llcommon/CMakeLists.txt | 10 +++++++++- indra/llcommon/llapp.cpp | 14 +++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 50e262ae7a..9c5481a977 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -14,6 +14,7 @@ include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) include(BUGSPLAT) +include(BuildVersion) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -255,7 +256,14 @@ set(llcommon_HEADER_FILES ) set_source_files_properties(${llcommon_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) + PROPERTIES HEADER_FILE_ONLY TRUE + ) + +# bring in version information for BugSplat crash reporting +set_source_files_properties(${llcommon_SOURCE_FILES} + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6ea1700ea8..3e652dbdb5 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -431,9 +431,17 @@ void LLApp::setupErrorHandling(bool second_instance) #if BUGSPLAT_ENABLED // TODOCP: populate these fields correctly static const wchar_t *bugdb_name = L"second_life_callum_test"; - static const wchar_t *app_name = L"SecondLifeViewer"; - static const wchar_t *app_version = L"1.0.0"; - gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name, (const __wchar_t *)app_version, NULL); + + // build (painfully) the app/channel name + #define stringize_inner(x) L#x + #define stringize_outer(x) stringize_inner(x) + std::wstring app_name(stringize_outer(LL_VIEWER_CHANNEL)); + + // build in real app version now we leveraged CMake to build in BuildVersion.cmake into LLCommon + wchar_t version_string[MAX_STRING]; + wsprintf(version_string, L"%d.%d.%d.%d", LL_VIEWER_VERSION_MAJOR, LL_VIEWER_VERSION_MINOR, LL_VIEWER_VERSION_PATCH, LL_VIEWER_VERSION_BUILD); + + gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name.c_str(), (const __wchar_t *)version_string, NULL); gBugSplatSender->setCallback(BugSplatExceptionCallback); #else -- cgit v1.3 From 508e754eb4501b9c3fbfbfde52ca7ae8ed0f06b7 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Thu, 14 Dec 2017 18:12:22 -0500 Subject: fix tab character coding style violation --- indra/llcommon/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 9c5481a977..c8e44d7ba4 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -257,13 +257,13 @@ set(llcommon_HEADER_FILES set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE - ) + ) # bring in version information for BugSplat crash reporting set_source_files_properties(${llcommon_SOURCE_FILES} PROPERTIES - COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake - ) + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake + ) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) -- cgit v1.3 From 3de5bab17459ed5bf0494d7bd2a531c473e20b7e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 11 May 2018 16:00:20 -0400 Subject: SL-821: Move BugSplat includes/libs from llcommon to newview. No C++ source in llcommon references any of the BugSplat code. --- indra/llcommon/CMakeLists.txt | 3 --- indra/newview/CMakeLists.txt | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index c8e44d7ba4..4eba1d5451 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,7 +13,6 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) -include(BUGSPLAT) include(BuildVersion) include_directories( @@ -23,7 +22,6 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIRECTORIES} ${URIPARSER_INCLUDE_DIRS} - ${BUGSPLAT_INCLUDE_DIR} ) # add_executable(lltreeiterators lltreeiterators.cpp) @@ -301,7 +299,6 @@ target_link_libraries( ${BOOST_SYSTEM_LIBRARY} ${GOOGLE_PERFTOOLS_LIBRARIES} ${URIPARSER_LIBRARIES} - ${BUGSPLAT_LIBRARIES} ) if (DARWIN) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b16713add..1fd0af0558 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -4,6 +4,7 @@ project(viewer) include(00-Common) include(Boost) +include(bugsplat) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -91,6 +92,7 @@ include_directories( ${LIBS_PREBUILT_DIR}/include/collada/1.4 ${LLAPPEARANCE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} + ${BUGSPLAT_INCLUDE_DIR} ) include_directories(SYSTEM @@ -1976,6 +1978,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLPHYSICS_LIBRARIES} ${LLPHYSICSEXTENSIONS_LIBRARIES} ${LLAPPEARANCE_LIBRARIES} + ${BUGSPLAT_LIBRARIES} ) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH -- cgit v1.3 From ed891c60de4169fa8ef4cc19e953e389cc4df60e Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 05:33:14 -0400 Subject: SL-821: Add LL_TO_WSTRING() macro to llpreprocessor.h. Also use existing LL_TO_STRING() macro to stringize LL_VIEWER_CHANNEL in llversioninfo.cpp and its tests. --- indra/llcommon/llpreprocessor.h | 2 ++ indra/newview/llversioninfo.cpp | 7 ++----- indra/newview/tests/llversioninfo_test.cpp | 6 ++---- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 2879038c36..ef015fdce4 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -198,6 +198,8 @@ #define LL_TO_STRING_HELPER(x) #x #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) +#define LL_TO_WSTRING_HELPER(x) L#x +#define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x) #define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg #define LL_GLUE_IMPL(x, y) x##y #define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y) diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 375dce485d..4e07223784 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -101,14 +101,11 @@ namespace { // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The // macro expands to the string name of the channel, but without quotes. We - // need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) - + // need to turn it into a quoted string. LL_TO_STRING() does that. /// Storage of the channel name the viewer is using. // The channel name is set by hardcoded constant, // or by calling LLVersionInfo::resetChannel() - std::string sWorkingChannelName(stringize_outer(LL_VIEWER_CHANNEL)); + std::string sWorkingChannelName(LL_TO_STRING(LL_VIEWER_CHANNEL)); // Storage for the "version and channel" string. // This will get reset too. diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 2f7a4e9601..58f0469552 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -33,10 +33,8 @@ // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The // macro expands to the string name of the channel, but without quotes. We -// need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) -#define ll_viewer_channel stringize_outer(LL_VIEWER_CHANNEL) +// need to turn it into a quoted string. LL_TO_STRING() does that. +#define ll_viewer_channel LL_TO_STRING(LL_VIEWER_CHANNEL) namespace tut { -- cgit v1.3 From c09d9c12e79fde83a87b2394c88b32e568271eda Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 05:45:36 -0400 Subject: SL-821: Add WSTRINGIZE() and DEWSTRINGIZE() macros for wide strings. Streamline convenience overload stringize(std::wstring); make convenience overload wstringize(std::string) symmetrically convert from UTF-8 string. Also eliminate STRINGIZE() et al. dependency on Boost.Phoenix: use lambdas instead. Using lambdas instead of template expansion necessitates reordering some code in wrapllerrs.h. --- indra/llcommon/stringize.h | 52 ++++++++++++++++++++++----------------- indra/llcommon/tests/wrapllerrs.h | 14 +++++------ 2 files changed, 36 insertions(+), 30 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index a5a90d7297..38dd198ad3 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -30,7 +30,6 @@ #define LL_STRINGIZE_H #include -#include #include /** @@ -53,12 +52,7 @@ std::basic_string gstringize(const T& item) */ inline std::string stringize(const std::wstring& item) { - LL_WARNS() << "WARNING: Possible narrowing" << LL_ENDL; - - std::string s; - - s = wstring_to_utf8str(item); - return gstringize(s); + return wstring_to_utf8str(item); } /** @@ -76,7 +70,10 @@ std::string stringize(const T& item) */ inline std::wstring wstringize(const std::string& item) { - return gstringize(item.c_str()); + // utf8str_to_wstring() returns LLWString, which isn't necessarily the + // same as std::wstring + LLWString s(utf8str_to_wstring(item)); + return std::wstring(s.begin(), s.end()); } /** @@ -91,10 +88,10 @@ std::wstring wstringize(const T& item) /** * stringize_f(functor) */ -template -std::string stringize_f(Functor const & f) +template +std::basic_string stringize_f(Functor const & f) { - std::ostringstream out; + std::basic_ostringstream out; f(out); return out.str(); } @@ -108,31 +105,37 @@ std::string stringize_f(Functor const & f) * return out.str(); * @endcode */ -#define STRINGIZE(EXPRESSION) (stringize_f(boost::phoenix::placeholders::arg1 << EXPRESSION)) +#define STRINGIZE(EXPRESSION) (stringize_f([&](std::ostream& out){ out << EXPRESSION; })) +/** + * WSTRINGIZE() is the wstring equivalent of STRINGIZE() + */ +#define WSTRINGIZE(EXPRESSION) (stringize_f([&](std::wostream& out){ out << EXPRESSION; })) /** * destringize(str) * defined for symmetry with stringize - * *NOTE - this has distinct behavior from boost::lexical_cast regarding + * @NOTE - this has distinct behavior from boost::lexical_cast regarding * leading/trailing whitespace and handling of bad_lexical_cast exceptions + * @NOTE - no need for dewstringize(), since passing std::wstring will Do The + * Right Thing */ -template -T destringize(std::string const & str) +template +T destringize(std::basic_string const & str) { - T val; - std::istringstream in(str); - in >> val; + T val; + std::basic_istringstream in(str); + in >> val; return val; } /** * destringize_f(str, functor) */ -template -void destringize_f(std::string const & str, Functor const & f) +template +void destringize_f(std::basic_string const & str, Functor const & f) { - std::istringstream in(str); + std::basic_istringstream in(str); f(in); } @@ -143,8 +146,11 @@ void destringize_f(std::string const & str, Functor const & f) * std::istringstream in(str); * in >> item1 >> item2 >> item3 ... ; * @endcode + * @NOTE - once we get generic lambdas, we shouldn't need DEWSTRINGIZE() any + * more since DESTRINGIZE() should do the right thing with a std::wstring. But + * until then, the lambda we pass must accept the right std::basic_istream. */ -#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::phoenix::placeholders::arg1 >> EXPRESSION))) - +#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::istream& in){in >> EXPRESSION;})) +#define DEWSTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::wistream& in){in >> EXPRESSION;})) #endif /* ! defined(LL_STRINGIZE_H) */ diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 9a4bbbd630..08fbf19b1c 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -109,6 +109,12 @@ public: mMessages.push_back(message); } + friend inline + std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) + { + return log.streamto(out); + } + /// Don't assume the message we want is necessarily the LAST log message /// emitted by the underlying code; search backwards through all messages /// for the sought string. @@ -126,7 +132,7 @@ public: throw tut::failure(STRINGIZE("failed to find '" << search << "' in captured log messages:\n" - << boost::ref(*this))); + << *this)); } std::ostream& streamto(std::ostream& out) const @@ -200,10 +206,4 @@ private: LLError::RecorderPtr mRecorder; }; -inline -std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) -{ - return log.streamto(out); -} - #endif /* ! defined(LL_WRAPLLERRS_H) */ -- cgit v1.3 From c5f618d096f05bdff91a5d384c46e26840f5a771 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 17 May 2018 06:53:42 -0400 Subject: SL-821: Move Windows BugSplat engagement from llcommon to newview. Use WSTRINGIZE(), LL_TO_WSTRING(), wstringize() to produce required wide strings. Use a lambda for callback that sends log file; use LLDir, if set, to find the log file. Introduce BUGSPLAT CMake variable to allow suppressing BugSplat. Make BUGSPLAT CMake variable set LL_BUGSPLAT for C++ compilations. Set viewer version macros on llappviewerwin32.cpp, llappviewerlinux.cpp and llappdelegate-objc.mm -- because BugSplat needs the viewer version data, and because the macOS BugSplat hook is engaged in an Objective-C++ function we override in the app delegate. --- indra/cmake/CMakeLists.txt | 1 + indra/cmake/bugsplat.cmake | 46 +++++++++++++++++------------ indra/llcommon/CMakeLists.txt | 10 +------ indra/llcommon/llapp.cpp | 60 ++------------------------------------ indra/llcommon/llapp.h | 10 +------ indra/newview/CMakeLists.txt | 23 ++++++++++++++- indra/newview/llappviewerwin32.cpp | 49 ++++++++++++++++++++++++++++--- 7 files changed, 101 insertions(+), 98 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 4a3ebe4835..84e1c5d6fd 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -12,6 +12,7 @@ set(cmake_SOURCE_FILES Audio.cmake BerkeleyDB.cmake Boost.cmake + bugsplat.cmake BuildVersion.cmake CEFPlugin.cmake CEFPlugin.cmake diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index e993979902..a7f4194905 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,20 +1,30 @@ -include(Prebuilt) +# BUGSPLAT can be set when launching the make using the argument -DBUGSPLAT:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with BUGSPLAT. +# Open source devs should use the -DBUGSPLAT:BOOL=ON then if they want to +# build with BugSplat, whether they are using USESYSTEMLIBS or not. +if (INSTALL_PROPRIETARY) + set(BUGSPLAT ON CACHE BOOL "Using BugSplat crash reporting library.") +endif (INSTALL_PROPRIETARY) -set(BUGSPLAT_FIND_QUIETLY ON) -set(BUGSPLAT_FIND_REQUIRED ON) +if (BUGSPLAT) + if (USESYSTEMLIBS) + set(BUGSPLAT_FIND_QUIETLY ON) + set(BUGSPLAT_FIND_REQUIRED ON) + include(FindBUGSPLAT) + else (USESYSTEMLIBS) + include(Prebuilt) + use_prebuilt_binary(bugsplat) + if (WINDOWS) + set(BUGSPLAT_LIBRARIES + ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib + ) + elseif (DARWIN) + find_library(BUGSPLAT_LIBRARIES BugsplatMac + PATHS "${ARCH_PREBUILT_DIRS_RELEASE}") + else (WINDOWS) -if (USESYSTEMLIBS) - include(FindBUGSPLAT) -else (USESYSTEMLIBS) - use_prebuilt_binary(bugsplat) - if (WINDOWS) - set(BUGSPLAT_LIBRARIES - ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib - ) - elseif (DARWIN) - - else (WINDOWS) - - endif (WINDOWS) - set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) -endif (USESYSTEMLIBS) + endif (WINDOWS) + set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) + endif (USESYSTEMLIBS) +endif (BUGSPLAT) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 4eba1d5451..d9eb13d65a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -13,7 +13,6 @@ include(GoogleBreakpad) include(Copy3rdPartyLibs) include(ZLIB) include(URIPARSER) -include(BuildVersion) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -254,14 +253,7 @@ set(llcommon_HEADER_FILES ) set_source_files_properties(${llcommon_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE - ) - -# bring in version information for BugSplat crash reporting -set_source_files_properties(${llcommon_SOURCE_FILES} - PROPERTIES - COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake - ) + PROPERTIES HEADER_FILE_ONLY TRUE) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 3e652dbdb5..6cc9e804d4 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -49,20 +49,6 @@ #include "google_breakpad/exception_handler.h" #include "stringize.h" #include "llcleanup.h" -#include "BugSplat.h" - -// TESTING ONLY - REMOVE FOR PRODUCTION -// (Want to only invoke BugSplat crash reporting in the same way we did for Breakpad - for Release viewers -// but need to test here in a ReleaseWithDebugInfo environment) -#if BUGSPLAT_ENABLED -#define LL_SEND_CRASH_REPORTS 1 -#endif - -// BugSplat crash reporting tool - http://bugsplat.com -#if BUGSPLAT_ENABLED -bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2); -MiniDmpSender *gBugSplatSender; -#endif // // Signal handling @@ -399,26 +385,6 @@ void EnableCrashingOnCrashes() } #endif -#if BUGSPLAT_ENABLED -bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2) -{ - switch (nCode) - { - case MDSCB_EXCEPTIONCODE: - { - // send the main viewer log file (Clearly a temporary hack since we don't have access to the gDir*** set of functions in newview - const std::string appdata = std::string(getenv("APPDATA")); - const std::string logfile = appdata + "\\SecondLife\\logs\\Secondlife.log"; - const std::wstring wide_logfile(logfile.begin(), logfile.end()); - gBugSplatSender->sendAdditionalFile((const __wchar_t *)wide_logfile.c_str()); - } - break; - } - - return false; -} -#endif - void LLApp::setupErrorHandling(bool second_instance) { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -427,25 +393,6 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS #if LL_SEND_CRASH_REPORTS - -#if BUGSPLAT_ENABLED - // TODOCP: populate these fields correctly - static const wchar_t *bugdb_name = L"second_life_callum_test"; - - // build (painfully) the app/channel name - #define stringize_inner(x) L#x - #define stringize_outer(x) stringize_inner(x) - std::wstring app_name(stringize_outer(LL_VIEWER_CHANNEL)); - - // build in real app version now we leveraged CMake to build in BuildVersion.cmake into LLCommon - wchar_t version_string[MAX_STRING]; - wsprintf(version_string, L"%d.%d.%d.%d", LL_VIEWER_VERSION_MAJOR, LL_VIEWER_VERSION_MINOR, LL_VIEWER_VERSION_PATCH, LL_VIEWER_VERSION_BUILD); - - gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name.c_str(), (const __wchar_t *)version_string, NULL); - - gBugSplatSender->setCallback(BugSplatExceptionCallback); -#else - EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -507,9 +454,8 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif // BUGSPLAT_ENABLED -#endif // LL_SEND_CRASH_REPORTS -#else // not LL_WINDOWS +#endif +#else // // Start up signal handling. // @@ -570,7 +516,7 @@ void LLApp::setupErrorHandling(bool second_instance) } #endif -#endif // LL_WINDOWS +#endif startErrorThread(); } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 5a4b7f13df..acd829d864 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -30,7 +30,6 @@ #include #include "llrun.h" #include "llsd.h" - // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -40,14 +39,6 @@ class LLLiveFile; #include #endif -// first version of Bugsplat (http://bugsplat.com) crash reporting tool -// is only supported on Windows - macOS to follow. -#define BUGSPLAT_ENABLED LL_WINDOWS - -#if BUGSPLAT_ENABLED -class __declspec(dllexport) MiniDmpSender; -#endif - typedef void (*LLAppErrorHandler)(); #if !LL_WINDOWS @@ -325,6 +316,7 @@ private: google_breakpad::ExceptionHandler * mExceptionHandler; + #if !LL_WINDOWS friend void default_unix_signal_handler(int signum, siginfo_t *info, void *); #endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1fd0af0558..2592b532c4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1354,6 +1354,11 @@ if (DARWIN) # This should be compiled with the viewer. LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm) + set_source_files_properties( + llappdelegate-objc.mm + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + ) find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) @@ -1366,6 +1371,7 @@ if (DARWIN) ${AGL_LIBRARY} ${IOKIT_LIBRARY} ${COREAUDIO_LIBRARY} + ${BUGSPLAT_LIBRARIES} ) # Add resource files to the project. @@ -1393,6 +1399,11 @@ endif (DARWIN) if (LINUX) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp) + set_source_files_properties( + llappviewerlinux.cpp + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + ) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") @@ -1409,6 +1420,11 @@ if (WINDOWS) llappviewerwin32.cpp llwindebug.cpp ) + set_source_files_properties( + llappviewerwin32.cpp + PROPERTIES + COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" + ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h @@ -1692,6 +1708,11 @@ if (SDL_FOUND) ) endif (SDL_FOUND) +if (BUGSPLAT) + set_property(TARGET ${VIEWER_BINARY_NAME} + PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (BUGSPLAT) + # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py) @@ -1790,7 +1811,7 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll ) endif (FMODEX) - + add_custom_command( OUTPUT ${CMAKE_CFG_INTDIR}/copy_touched.bat COMMAND ${PYTHON_EXECUTABLE} diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 48b3a1c485..8a014c55d7 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -66,8 +66,18 @@ #endif #include "stringize.h" +#include "lldir.h" #include + +// Bugsplat (http://bugsplat.com) crash reporting tool +#ifdef LL_BUGSPLAT +#include "BugSplat.h" + +// FIXME: need a production BugSplat database name +static const wchar_t *bugdb_name = L"second_life_callum_test"; +#endif + namespace { void (*gOldTerminateHandler)() = NULL; @@ -495,15 +505,46 @@ bool LLAppViewerWin32::init() LLWinDebug::instance(); #endif -#if LL_WINDOWS #if LL_SEND_CRASH_REPORTS - +#if ! defined(LL_BUGSPLAT) LLAppViewer* pApp = LLAppViewer::instance(); pApp->initCrashReporting(); -#endif -#endif +#else // LL_BUGSPLAT + + std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << + LL_VIEWER_VERSION_MINOR << '.' << + LL_VIEWER_VERSION_PATCH << '.' << + LL_VIEWER_VERSION_BUILD)); + + auto sender = new MiniDmpSender( + bugdb_name, LL_TO_WSTRING(LL_VIEWER_CHANNEL), version_string.c_str(), nullptr); + sender->setCallback( + [sender](unsigned int nCode, void* lpVal1, void* lpVal2) + { + // If we haven't yet initialized LLDir, don't bother trying to + // find our log file. + // Alternatively -- if we might encounter trouble trying to query + // LLDir during crash cleanup -- consider making gDirUtilp an + // LLPounceable, and attach a callback that stores the pathname to + // the log file here. + if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) + { + // send the main viewer log file + // widen to wstring, then pass c_str() + sender->sendAdditionalFile( + wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); + } + + return false; + }); + + LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) + << version_string << ')' << LL_ENDL; + +#endif // LL_BUGSPLAT +#endif // LL_SEND_CRASH_REPORTS bool success = LLAppViewer::init(); -- cgit v1.3 From ac2604a039bb9477cf9102dfccd77619a6061d7a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jun 2018 11:31:17 -0400 Subject: SL-821: Avoid Breakpad (and signal handling in general) for BugSplat. Pass LL_BUGSPLAT into llapp.cpp compile to be able to detect that. --- indra/llcommon/CMakeLists.txt | 5 +++++ indra/llcommon/llapp.cpp | 23 ++++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d9eb13d65a..8977acb873 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -255,6 +255,11 @@ set(llcommon_HEADER_FILES set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +if (DEFINED ENV{BUGSPLAT_DB}) + set_source_files_properties(llapp.cpp + PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (DEFINED ENV{BUGSPLAT_DB}) + list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) if(LLCOMMON_LINK_SHARED) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6cc9e804d4..421af3006e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -392,7 +392,7 @@ void LLApp::setupErrorHandling(bool second_instance) #if LL_WINDOWS -#if LL_SEND_CRASH_REPORTS +#if LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT) EnableCrashingOnCrashes(); // This sets a callback to handle w32 signals to the console window. @@ -454,8 +454,15 @@ void LLApp::setupErrorHandling(bool second_instance) mExceptionHandler->set_handle_debug_exceptions(true); } } -#endif -#else +#endif // LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT) +#else // ! LL_WINDOWS + +#if defined(LL_BUGSPLAT) + // Don't install our own signal handlers -- BugSplat needs to hook them, + // or it's completely ineffectual. + bool installHandler = false; + +#else // ! LL_BUGSPLAT // // Start up signal handling. // @@ -463,9 +470,11 @@ void LLApp::setupErrorHandling(bool second_instance) // thread, asynchronous signals can be delivered to any thread (in theory) // setup_signals(); - + // Add google breakpad exception handler configured for Darwin/Linux. bool installHandler = true; +#endif // ! LL_BUGSPLAT + #if LL_DARWIN // For the special case of Darwin, we do not want to install the handler if // the process is being debugged as the app will exit with value ABRT (6) if @@ -498,7 +507,7 @@ void LLApp::setupErrorHandling(bool second_instance) // installing the handler. installHandler = true; } - #endif + #endif // ! LL_RELEASE_FOR_DOWNLOAD if(installHandler && (mExceptionHandler == 0)) { @@ -514,9 +523,9 @@ void LLApp::setupErrorHandling(bool second_instance) google_breakpad::MinidumpDescriptor desc(mDumpPath); mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1); } -#endif +#endif // LL_LINUX -#endif +#endif // ! LL_WINDOWS startErrorThread(); } -- cgit v1.3 From cd52724ef8f8a19ebe28c73f39a582b56fb58093 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 28 Jun 2018 21:49:07 -0400 Subject: DRTVWR-447: Suppress BugSplat UI; auto-fill certain BugSplat data. Direct BugSplat to send crash reports without prompting, on both Windows and Mac. Add a mechanism by which code called after LL_ERRS() can retrieve the fatal log message string. (How did the crash logger extract that for Linden crash logging?) Add that fatal message to crash reports on Windows. But as BugsplatMac is engaged only on the run _after_ the crash, we no longer have that message in memory. Also add user name and region location to Windows crash reports. On Mac, (a) we don't have the information from the previous run and (b) BugsplatMac doesn't provide an API to attach that information to the crash report. Add Mac logging to indicate the success or failure of sending the crash report. Add Windows logging to indicate we're about to send. --- indra/llcommon/llerror.cpp | 33 ++++++++++++------- indra/llcommon/llerrorcontrol.h | 3 ++ indra/newview/llappdelegate-objc.mm | 34 +++++++++++++------ indra/newview/llappviewermacosx-for-objc.h | 2 ++ indra/newview/llappviewermacosx.cpp | 12 +++++++ indra/newview/llappviewerwin32.cpp | 53 +++++++++++++++++++++--------- 6 files changed, 101 insertions(+), 36 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f31a054139..b5e7e81f21 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -377,6 +377,7 @@ namespace public: std::ostringstream messageStream; bool messageStreamInUse; + std::string mFatalMessage; void addCallSite(LLError::CallSite&); void invalidateCallSites(); @@ -670,11 +671,16 @@ namespace LLError s->mCrashFunction = f; } - FatalFunction getFatalFunction() - { + FatalFunction getFatalFunction() + { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - return s->mCrashFunction; - } + return s->mCrashFunction; + } + + std::string getFatalMessage() + { + return Globals::getInstance()->mFatalMessage; + } void setTimeFunction(TimeFunction f) { @@ -1194,7 +1200,7 @@ namespace LLError { writeToRecorders(site, "error", true, true, true, false, false); } - + std::ostringstream message_stream; if (site.mPrintOnce) @@ -1219,14 +1225,19 @@ namespace LLError s->mUniqueLogMessages[message] = 1; } } - + message_stream << message; - - writeToRecorders(site, message_stream.str()); - - if (site.mLevel == LEVEL_ERROR && s->mCrashFunction) + std::string message_line(message_stream.str()); + + writeToRecorders(site, message_line); + + if (site.mLevel == LEVEL_ERROR) { - s->mCrashFunction(message_stream.str()); + g->mFatalMessage = message_line; + if (s->mCrashFunction) + { + s->mCrashFunction(message_line); + } } } } diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index caf2ba72c2..ddbcdc94a0 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -102,6 +102,9 @@ namespace LLError LL_COMMON_API FatalFunction getFatalFunction(); // Retrieve the previously-set FatalFunction + LL_COMMON_API std::string getFatalMessage(); + // Retrieve the message last passed to FatalFunction, if any + /// temporarily override the FatalFunction for the duration of a /// particular scope, e.g. for unit tests class LL_COMMON_API OverrideFatalFunction diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 4510f4070f..82e49540a4 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -74,9 +74,9 @@ #if defined(LL_BUGSPLAT) // https://www.bugsplat.com/docs/platforms/os-x#initialization -// [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; -// [BugsplatStartupManager sharedManager].askUserDetails = NO; - [BugsplatStartupManager sharedManager].delegate = self; + [BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; + [BugsplatStartupManager sharedManager].askUserDetails = NO; + [BugsplatStartupManager sharedManager].delegate = self; [[BugsplatStartupManager sharedManager] start]; #endif } @@ -196,17 +196,20 @@ #if defined(LL_BUGSPLAT) -#if 0 -// Apparently this override method only contributes the User Description field -// of BugSplat's All Crashes table. Despite the method name, it would seem to -// be a bad place to try to stuff all of SecondLife.log. - (NSString *)applicationLogForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { -// return NSStringFromSelector(_cmd); infos("Reached applicationLogForBugsplatStartupManager"); - return @"[contents of SecondLife.log]"; + // Apparently this override method only contributes the User Description + // field of BugSplat's All Crashes table. Despite the method name, it + // would seem to be a bad place to try to stuff all of SecondLife.log. + return [NSString stringWithCString:getFatalMessage().c_str() + encoding:NSUTF8StringEncoding]; +} + +- (void)bugsplatStartupManagerWillSendCrashReport:(BugsplatStartupManager *)bugsplatStartupManager +{ + infos("Reached bugsplatStartupManagerWillSendCrashReport"); } -#endif - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { // We get the *old* log file pathname (for SecondLife.old) because it's on @@ -228,6 +231,17 @@ return attachment; } +- (void)bugsplatStartupManagerDidFinishSendingCrashReport:(BugsplatStartupManager *)bugsplatStartupManager +{ + infos("Sent crash report to BugSplat"); +} + +- (void)bugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager didFailWithError:(NSError *)error +{ + // TODO: message string from NSError + infos("Could not send crash report to BugSplat"); +} + #endif // LL_BUGSPLAT @end diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index c439297611..ac85d7e8c3 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -30,6 +30,8 @@ bool pumpMainLoop(); void handleQuit(); void cleanupViewer(); std::string getOldLogFilePathname(); +std::string getFatalMessage(); +std::string getAgentFullname(); void infos(const std::string& message); #endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index d014e992f9..c3a3c3284a 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -45,6 +45,8 @@ #include "llmd5.h" #include "llfloaterworldmap.h" #include "llurldispatcher.h" +#include "llerrorcontrol.h" +#include "llvoavatarself.h" // for gAgentAvatarp->getFullname() #include #ifdef LL_CARBON_CRASH_HANDLER #include @@ -153,6 +155,16 @@ std::string getOldLogFilePathname() return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); } +std::string getFatalMessage() +{ + return LLError::getFatalMessage(); +} + +std::string getAgentFullname() +{ + return gAgentAvatarp? gAgentAvatarp->getFullname() : std::string(); +} + void infos(const std::string& message) { LL_INFOS() << message << LL_ENDL; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 247b94db3e..1e135fa229 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -67,6 +67,7 @@ #include "stringize.h" #include "lldir.h" +#include "llerrorcontrol.h" #include #include @@ -74,7 +75,10 @@ // Bugsplat (http://bugsplat.com) crash reporting tool #ifdef LL_BUGSPLAT #include "BugSplat.h" -#include "reader.h" // JsonCpp +#include "reader.h" // JsonCpp +#include "llagent.h" // for agent location +#include "llviewerregion.h" +#include "llvoavatarself.h" // for agent name namespace { @@ -85,7 +89,8 @@ namespace // std::basic_string instance will survive until the function returns. // Calling c_str() on a std::basic_string local to wunder() would be // Undefined Behavior: we'd be left with a pointer into a destroyed - // std::basic_string instance. + // std::basic_string instance. But we can do that with a macro... + #define WCSTR(string) wunder(string).c_str() // It would be nice if, when wchar_t is the same as __wchar_t, this whole // function would optimize away. However, we use it only for the arguments @@ -111,19 +116,35 @@ namespace bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) { - // If we haven't yet initialized LLDir, don't bother trying to - // find our log file. - // Alternatively -- if we might encounter trouble trying to query - // LLDir during crash cleanup -- consider making gDirUtilp an - // LLPounceable, and attach a callback that stores the pathname to - // the log file here. - if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) + if (nCode == MDSCB_EXCEPTIONCODE) { // send the main viewer log file // widen to wstring, convert to __wchar_t, then pass c_str() sBugSplatSender->sendAdditionalFile( - wunder(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); - } + WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"))); + + if (gAgentAvatarp) + { + // user name, when we have it + sBugSplatSender->setDefaultUserName(WCSTR(gAgentAvatarp->getFullname())); + } + + // LL_ERRS message, when there is one + sBugSplatSender->setDefaultUserDescription(WCSTR(LLError::getFatalMessage())); + + if (gAgent.getRegion()) + { + // region location, when we have it + LLVector3 loc = gAgent.getPositionAgent(); + sBugSplatSender->resetAppIdentifier( + WCSTR(STRINGIZE(gAgent.getRegion()->getName() + << '/' << loc.mV[0] + << '/' << loc.mV[1] + << '/' << loc.mV[2]))); + } + + LL_INFOS() << "Sending crash report to BugSplat." << LL_ENDL; + } // MDSCB_EXCEPTIONCODE return false; } @@ -603,10 +624,12 @@ bool LLAppViewerWin32::init() // have to convert normal wide strings to strings of __wchar_t sBugSplatSender = new MiniDmpSender( - wunder(BugSplat_DB.asString()).c_str(), - wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), - wunder(version_string).c_str(), - nullptr); + 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 sBugSplatSender->setCallback(bugsplatSendLog); // engage stringize() overload that converts from wstring -- cgit v1.3