From f648758c2a3da2dd03c8f57e98598c085b2030a6 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 16 Jan 2019 11:05:55 -0500 Subject: SL-10297: Modify LL_ERRS and other deliberate crashes to avoid a common stack frame --- indra/newview/llappviewer.cpp | 89 +++++++------------------------------------ 1 file changed, 14 insertions(+), 75 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a33e978c0a..e6ba3e4f7c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -751,17 +751,6 @@ public: } }; -namespace { -// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide -// this little helper function. -void fast_exit(int rc) -{ - _exit(rc); -} - - -} - bool LLAppViewer::init() { @@ -801,19 +790,6 @@ bool LLAppViewer::init() initMaxHeapSize() ; LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); - - // Although initLoggingAndGetLastDuration() is the right place to mess with - // setFatalFunction(), we can't query gSavedSettings until after - // initConfiguration(). - S32 rc(gSavedSettings.getS32("QAModeTermCode")); - if (rc >= 0) - { - // QAModeTermCode set, terminate with that rc on LL_ERRS. Use - // fast_exit() rather than exit() because normal cleanup depends too - // much on successful startup! - LLError::setFatalFunction(boost::bind(fast_exit, rc)); - } - mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // Initialize the non-LLCurl libcurl library. Should be called @@ -2120,28 +2096,9 @@ bool LLAppViewer::cleanup() return true; } -// A callback for LL_ERRS() to call during the watchdog error. -void watchdog_llerrs_callback(const std::string &error_string) -{ - gLLErrorActivated = true; - gDebugInfo["FatalMessage"] = error_string; LLAppViewer::instance()->writeDebugInfo(); -#ifdef LL_WINDOWS - RaiseException(0,0,0,0); -#else - raise(SIGQUIT); -#endif -} - -// A callback for the watchdog to call. -void watchdog_killer_callback() -{ - LLError::setFatalFunction(watchdog_llerrs_callback); - LL_ERRS() << "Watchdog killer event" << LL_ENDL; -} - bool LLAppViewer::initThreads() { static const bool enable_threads = true; @@ -2176,24 +2133,6 @@ bool LLAppViewer::initThreads() return true; } -void errorCallback(const std::string &error_string) -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD - OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); -#endif - - //Set the ErrorActivated global so we know to create a marker file - gLLErrorActivated = true; - - gDebugInfo["FatalMessage"] = error_string; - // We're not already crashing -- we simply *intend* to crash. Since we - // haven't actually trashed anything yet, we can afford to write the whole - // static info file. - LLAppViewer::instance()->writeDebugInfo(); - - LLError::crashAndLoop(error_string); -} - void LLAppViewer::initLoggingAndGetLastDuration() { // @@ -2202,8 +2141,6 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ); - LLError::setFatalFunction(errorCallback); - //LLError::setTimeFunction(getRuntime); // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, @@ -2952,6 +2889,7 @@ bool LLAppViewer::initWindow() // Need to load feature table before cheking to start watchdog. bool use_watchdog = false; int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); + if (watchdog_enabled_setting == -1) { use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); @@ -2962,11 +2900,16 @@ bool LLAppViewer::initWindow() use_watchdog = bool(watchdog_enabled_setting); } + LL_INFOS("AppInit") << "watchdog" + << (use_watchdog ? " " : " NOT ") + << "enabled" + << " (setting = " << watchdog_enabled_setting << ")" + << LL_ENDL; + if (use_watchdog) { - LLWatchdog::getInstance()->init(watchdog_killer_callback); + LLWatchdog::getInstance()->init(); } - LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL; LLNotificationsUI::LLNotificationManager::getInstance(); @@ -3409,12 +3352,10 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["MainloopThreadID"] = (S32)thread_id; #endif - // "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; + // "CrashNotHandled" is obsolete; it used (not very successsfully) + // to try to distinguish crashes from freezes + gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false; + gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); // 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 @@ -3567,10 +3508,6 @@ void LLAppViewer::handleViewerCrash() 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 @@ -3642,6 +3579,8 @@ void LLAppViewer::handleViewerCrash() if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]); + gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage(); + // Close the debug file pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead. } -- cgit v1.3 From fc90cad4f366c4bb85add832a2fa8137b1f120ff Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 16 Jan 2019 16:42:34 -0500 Subject: change the default crash type from "freeze" to "other" --- build.sh | 20 ++++++++++++++++---- indra/newview/llappviewer.cpp | 9 ++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/build.sh b/build.sh index 875b39f9c1..9f070f2d10 100755 --- a/build.sh +++ b/build.sh @@ -412,6 +412,15 @@ then fi fi +# Some of the uploads takes a long time to finish in the codeticket backend, +# causing the next codeticket upload attempt to fail. +# Inserting this after each potentially large upload may prevent those errors. +# JJ is making changes to Codeticket that we hope will eliminate this failure, then this can be removed +wait_for_codeticket() +{ + sleep $(( 60 * 6 )) +} + # check status and upload results to S3 if $succeeded then @@ -428,6 +437,7 @@ then # Upload base package. python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \ || fatal "Upload of installer failed" + wait_for_codeticket # Upload additional packages. for package_id in $additional_packages @@ -437,6 +447,7 @@ then then python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \ || fatal "Upload of installer $package_id failed" + wait_for_codeticket else record_failure "Failed to find additional package for '$package_id'." fi @@ -447,12 +458,10 @@ then # nat 2016-12-22: without RELEASE_CRASH_REPORTING, we have no symbol file. if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ] then - # This next upload is a frequent failure; see if giving the last one some time helps - # JJ is making changes to Codeticket that we hope will eliminate this failure soon - sleep 30 # Upload crash reporter file python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \ || fatal "Upload of symbolfile failed" + wait_for_codeticket fi # Upload the llphysicsextensions_tpv package, if one was produced @@ -460,6 +469,9 @@ then if [ -r "$build_dir/llphysicsextensions_package" ] then llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package) + # This next upload is a frequent failure; see if giving the last one some time helps + # JJ is making changes to Codeticket that we hope will eliminate this failure soon + sleep 300 python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \ || fatal "Upload of physics extensions package failed" fi @@ -470,6 +482,7 @@ then for extension in ${build_dir}/packages/upload-extensions/*.sh; do begin_section "Upload Extension $extension" . $extension + wait_for_codeticket end_section "Upload Extension $extension" done fi @@ -479,7 +492,6 @@ then record_event "skipping upload of installer" fi - else record_event "skipping upload of installer due to failed build" fi diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e6ba3e4f7c..1fda07edd6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3508,6 +3508,10 @@ void LLAppViewer::handleViewerCrash() 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 @@ -3680,8 +3684,11 @@ void LLAppViewer::processMarkerFiles() { // the file existed, is ours, and matched our version, so we can report on what it says LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL; +# if LL_BUGSPLAT + gLastExecEvent = LAST_EXEC_OTHER_CRASH; +# else gLastExecEvent = LAST_EXEC_FROZE; - +# endif } else { -- cgit v1.3 From e409c0492f1b1ce63606c0b693c92cdb36dcc28b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Sat, 2 Mar 2019 11:58:11 -0500 Subject: convert to an explicit USE_BUGSPLAT switch in cmake, revise LL_ERRS approach --- build.sh | 5 ---- indra/CMakeLists.txt | 10 +++++++ indra/cmake/Copy3rdPartyLibs.cmake | 4 +-- indra/cmake/LLAddBuildTest.cmake | 13 ++++++++- indra/cmake/Variables.cmake | 1 - indra/cmake/bugsplat.cmake | 53 +++++++++++++++++++--------------- indra/llcommon/CMakeLists.txt | 9 +++--- indra/llcommon/llerror.cpp | 21 +++++++++----- indra/llcommon/llerror.h | 20 +++++++------ indra/llcommon/llerrorcontrol.h | 14 +++++++-- indra/llcommon/llleap.cpp | 30 +------------------ indra/llcommon/tests/wrapllerrs.h | 5 ++-- indra/llcorehttp/CMakeLists.txt | 1 + indra/llimage/CMakeLists.txt | 1 + indra/llmath/CMakeLists.txt | 1 + indra/newview/CMakeLists.txt | 36 +++++++++++------------ indra/newview/llappviewer.cpp | 59 +++++++++++++++++++++++++++++++++----- indra/newview/llwatchdog.cpp | 8 +++--- indra/test/CMakeLists.txt | 6 +++- indra/test/test.cpp | 10 +++---- 20 files changed, 185 insertions(+), 122 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/build.sh b/build.sh index 9f070f2d10..aa6ba475a3 100755 --- a/build.sh +++ b/build.sh @@ -129,11 +129,6 @@ pre_build() then # show that we're doing this, just not the contents echo source "$bugsplat_sh" source "$bugsplat_sh" - # important: we test this and use its value in [grand-]child processes - if [ -n "${BUGSPLAT_DB:-}" ] - then echo export BUGSPLAT_DB - export BUGSPLAT_DB - fi fi set -x diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 62a8f3f003..cf6029c4ae 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -13,6 +13,7 @@ project(${ROOT_PROJECT_NAME}) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") include(Variables) +include(bugsplat) include(BuildVersion) if (NOT CMAKE_BUILD_TYPE) @@ -89,6 +90,15 @@ set_property( PROPERTY VS_STARTUP_PROJECT secondlife-bin ) +if (USE_BUGSPLAT) + if (BUGSPLAT_DB) + message(STATUS "Building with BugSplat; database '${BUGSPLAT_DB}'") + else (BUGSPLAT_DB) + message(WARNING "Building with BugSplat, but no database name set (BUGSPLAT_DB)") + endif (BUGSPLAT_DB) +else (USE_BUGSPLAT) + message(STATUS "Not building with BugSplat") +endif (USE_BUGSPLAT) if (LL_TESTS) # Define after the custom targets are created so # individual apps can add themselves as dependencies diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index c73a1fdb47..ebb6379aed 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -50,7 +50,7 @@ if(WINDOWS) # Filenames are different for 32/64 bit BugSplat file and we don't # have any control over them so need to branch. - if (BUGSPLAT_DB) + if (USE_BUGSPLAT) if(ADDRESS_SIZE EQUAL 32) set(release_files ${release_files} BugSplat.dll) set(release_files ${release_files} BugSplatRc.dll) @@ -60,7 +60,7 @@ if(WINDOWS) set(release_files ${release_files} BugSplatRc64.dll) set(release_files ${release_files} BsSndRpt64.exe) endif(ADDRESS_SIZE EQUAL 32) - endif (BUGSPLAT_DB) + endif (USE_BUGSPLAT) if (FMODEX) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index b3f42c1a5e..fa10a9d443 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -2,6 +2,7 @@ include(00-Common) include(LLTestCommand) include(GoogleMock) +include(bugsplat) include(Tut) #***************************************************************************** @@ -22,7 +23,6 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) # there is another branch that will conflict heavily with any changes here. INCLUDE(GoogleMock) - IF(LL_TEST_VERBOSE) MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") ENDIF(LL_TEST_VERBOSE) @@ -87,6 +87,12 @@ INCLUDE(GoogleMock) IF(LL_TEST_VERBOSE) MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}") ENDIF(LL_TEST_VERBOSE) + + if (USE_BUGSPLAT) + SET_PROPERTY(SOURCE ${${name}_test_SOURCE_FILES} + APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") + endif (USE_BUGSPLAT) + # Headers GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES) SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) @@ -223,6 +229,11 @@ FUNCTION(LL_ADD_INTEGRATION_TEST SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") endif(USESYSTEMLIBS) + if (USE_BUGSPLAT) + SET_PROPERTY(SOURCE ${source_files} + APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") + endif (USE_BUGSPLAT) + # The following was copied to llcorehttp/CMakeLists.txt's texture_load target. # Any changes made here should be replicated there. if (WINDOWS) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index a5770c5528..c81b22e572 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -34,7 +34,6 @@ set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable fo set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)") set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism") set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files") -set(BUGSPLAT_DB "" CACHE STRING "BugSplat database name, if BugSplat crash reporting is desired") if(LIBS_CLOSED_DIR) file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR) diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake index 59644b73ce..749ea05403 100644 --- a/indra/cmake/bugsplat.cmake +++ b/indra/cmake/bugsplat.cmake @@ -1,25 +1,32 @@ -# BugSplat is engaged by setting BUGSPLAT_DB to the target BugSplat database -# name. -if (BUGSPLAT_DB) - if (USESYSTEMLIBS) - message(STATUS "Looking for system BugSplat") - set(BUGSPLAT_FIND_QUIETLY ON) - set(BUGSPLAT_FIND_REQUIRED ON) - include(FindBUGSPLAT) - else (USESYSTEMLIBS) - message(STATUS "Engaging autobuild BugSplat") - 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 (INSTALL_PROPRIETARY) + set(USE_BUGSPLAT ON CACHE BOOL "Use the BugSplat crash reporting system") +else (INSTALL_PROPRIETARY) + set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system") +endif (INSTALL_PROPRIETARY) + +if (USE_BUGSPLAT) + if (NOT 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) + message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF") + endif (WINDOWS) + else (NOT USESYSTEMLIBS) + set(BUGSPLAT_FIND_QUIETLY ON) + set(BUGSPLAT_FIND_REQUIRED ON) + include(FindBUGSPLAT) + endif (NOT USESYSTEMLIBS) + + set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name") - endif (WINDOWS) set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) - endif (USESYSTEMLIBS) -endif (BUGSPLAT_DB) + set(BUGSPLAT_DEFINE "LL_BUGSPLAT") +endif (USE_BUGSPLAT) + diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af41b9e460..e3afa5eca4 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -5,6 +5,7 @@ project(llcommon) include(00-Common) include(LLCommon) +include(bugsplat) include(Linking) include(Boost) include(LLSharedLibs) @@ -257,10 +258,10 @@ set(llcommon_HEADER_FILES set_source_files_properties(${llcommon_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) -if (BUGSPLAT_DB) - set_source_files_properties(llapp.cpp - PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT") -endif (BUGSPLAT_DB) +if (USE_BUGSPLAT) + set_source_files_properties(${llcommon_SOURCE_FILES} + PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +endif (USE_BUGSPLAT) list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 0ddce353f1..77d7fe1b24 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -25,6 +25,7 @@ * $/LicenseInfo$ */ +#define _LLERROR_CPP_ #include "linden_common.h" #include "llerror.h" @@ -724,7 +725,7 @@ namespace LLError s->mCrashFunction = fatal_function; } - void restoreCrashOnError() + void restoreCrashOnError() { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); s->mCrashFunction = NULL; @@ -1310,7 +1311,7 @@ namespace LLError LLMutexTrylock lock(&gLogMutex,5); if (!lock.isLocked()) { - return true; + return false; // because this wasn't logged, it cannot be fatal } // If we hit a logging request very late during shutdown processing, @@ -1318,7 +1319,7 @@ namespace LLError // DO NOT resurrect them. if (Settings::wasDeleted() || Globals::wasDeleted()) { - return true; + return false; // because this wasn't logged, it cannot be fatal } Globals* g = Globals::getInstance(); @@ -1352,7 +1353,7 @@ namespace LLError } else { - return true; + return false; // because this wasn't logged, it cannot be fatal } } else @@ -1372,11 +1373,17 @@ namespace LLError if (s->mCrashFunction) { s->mCrashFunction(message); - return false; + return false; // because an override is in effect + } + else + { + return true; // calling macro should crash } } - - return true; + else + { + return false; // not ERROR, so do not crash + } } } diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index cbade88f61..07aa5c6f8b 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -202,7 +202,7 @@ namespace LLError static void flush(std::ostringstream* out, char* message); - // returns false iff there is a fatal crash override in effect + // returns false iff the calling macro should crash static bool flush(std::ostringstream*, const CallSite&); static std::string demangle(const char* mangled); @@ -371,18 +371,22 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_NEWLINE '\n' +#ifdef _LLERROR_CPP_ +volatile int* gCauseCrash = NULL; +#else +volatile extern int* gCauseCrash; +#endif // _LLERROR_CPP_ + // Use this only in LL_ERRS or in a place that LL_ERRS may not be used -#define LLERROR_CRASH \ -{ \ - int* make_me_crash = NULL;\ - *make_me_crash = 0; \ - exit(*make_me_crash); \ +#define LLERROR_CRASH \ +{ \ + *gCauseCrash = 0; \ + exit(*gCauseCrash); \ } #define LL_ENDL \ LLError::End(); \ - if (LLError::Log::flush(_out, _site) \ - && _site.mLevel == LLError::LEVEL_ERROR) \ + if (LLError::Log::flush(_out, _site)) \ LLERROR_CRASH \ } \ } while(0) diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 7ca6ddb737..af46430f74 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -92,11 +92,19 @@ namespace LLError /* Control functions. */ + typedef boost::function FatalFunction; - LL_COMMON_API void overrideCrashOnError(const FatalFunction&); - LL_COMMON_API void restoreCrashOnError(); - + /// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code + LL_COMMON_API void overrideCrashOnError(const FatalFunction&); + // The fatal function will be called when an message of LEVEL_ERROR + // is logged. Note: supressing a LEVEL_ERROR message from being logged + // (by, for example, setting a class level to LEVEL_NONE), will keep + // the that message from causing the fatal funciton to be invoked. + + /// Undo the effect of the overrideCrashOnError above + LL_COMMON_API void restoreCrashOnError(); + LL_COMMON_API std::string getFatalMessage(); // Retrieve the message last passed to LL_ERRS, if any diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index f7bfa36bb5..bf20c87c89 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -59,6 +59,7 @@ public: // pump name -- so it should NOT need tweaking for uniqueness. mReplyPump(LLUUID::generateNewID().asString()), mExpect(0), + // Instantiate a distinct LLLeapListener for this plugin. (Every // plugin will want its own collection of managed listeners, etc.) // Pass it a callback to our connect() method, so it can send events @@ -144,9 +145,6 @@ public: mStderrConnection = childerr.getPump() .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1)); - // For our lifespan, intercept any LL_ERRS so we can notify plugin - LLError::overrideCrashOnError(boost::bind(&LLLeapImpl::fatalFunction, this, _1)); - // Send child a preliminary event reporting our own reply-pump name -- // which would otherwise be pretty tricky to guess! wstdin(mReplyPump.getName(), @@ -161,8 +159,6 @@ public: virtual ~LLLeapImpl() { LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL; - // Restore original fatal crash behavior for LL_ERRS - LLError::restoreCrashOnError(); } // Listener for failed launch attempt @@ -376,30 +372,6 @@ public: return false; } - void fatalFunction(const std::string& error) - { - // Notify plugin - LLSD event; - event["type"] = "error"; - event["error"] = error; - mReplyPump.post(event); - - // All the above really accomplished was to buffer the serialized - // event in our WritePipe. Have to pump mainloop a couple times to - // really write it out there... but time out in case we can't write. - LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - LLSD nop; - F64 until = (LLTimer::getElapsedSeconds() + 2).value(); - while (childin.size() && LLTimer::getElapsedSeconds() < until) - { - mainloop.post(nop); - } - - // go ahead and do the crash that LLError would have done - LLERROR_CRASH - } - private: /// We always want to listen on mReplyPump with wstdin(); under some /// circumstances we'll also echo other LLEventPumps to the plugin. diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index b280271476..fedc17dbe9 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -50,11 +50,11 @@ extern void wouldHaveCrashed(const std::string& message); struct WrapLLErrs { - WrapLLErrs(): + WrapLLErrs() // Resetting Settings discards the default Recorder that writes to // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the // console output of successful tests, potentially confusing things. - mPriorErrorSettings(LLError::saveAndResetSettings()) + :mPriorErrorSettings(LLError::saveAndResetSettings()) { // Make LL_ERRS call our own operator() method LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1)); @@ -210,6 +210,7 @@ public: { LLError::removeRecorder(mRecorder); LLError::restoreSettings(mOldSettings); + LLError::restoreCrashOnError(); } /// Don't assume the message we want is necessarily the LAST log message diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 9dbc6f447e..286c275b90 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -13,6 +13,7 @@ include(LLAddBuildTest) include(LLMessage) include(LLCommon) include(Tut) +include(bugsplat) include_directories (${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index 293ada7548..28b8e8c06d 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -11,6 +11,7 @@ include(LLKDU) include(LLImageJ2COJ) include(ZLIB) include(LLAddBuildTest) +include(bugsplat) include(Tut) include_directories( diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 379c3ee9ea..625459823c 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -4,6 +4,7 @@ project(llmath) include(00-Common) include(LLCommon) +include(bugsplat) include(Boost) include_directories( diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 04f6c9b7f0..bbfa838827 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -8,9 +8,7 @@ include(00-Common) include(Linking) include(Boost) -if (BUGSPLAT_DB) - include(bugsplat) -endif (BUGSPLAT_DB) +include(bugsplat) include(BuildPackagesInfo) include(BuildVersion) include(CMakeCopyIfDifferent) @@ -97,18 +95,18 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -if (BUGSPLAT_DB) - include_directories( - ${BUGSPLAT_INCLUDE_DIR} - ) -endif (BUGSPLAT_DB) - include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLXML_SYSTEM_INCLUDE_DIRS} ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ) +if (USE_BUGSPLAT) + include_directories(AFTER + ${BUGSPLAT_INCLUDE_DIR} + ) +endif (USE_BUGSPLAT) + set(viewer_SOURCE_FILES groupchatlistener.cpp llaccountingcostmanager.cpp @@ -1390,11 +1388,11 @@ if (DARWIN) ${COREAUDIO_LIBRARY} ) - if (BUGSPLAT_DB) + if (USE_BUGSPLAT) list(APPEND viewer_LIBRARIES ${BUGSPLAT_LIBRARIES} ) - endif (BUGSPLAT_DB) + endif (USE_BUGSPLAT) # Add resource files to the project. set(viewer_RESOURCE_FILES @@ -1729,10 +1727,10 @@ if (SDL_FOUND) ) endif (SDL_FOUND) -if (BUGSPLAT_DB) +if (USE_BUGSPLAT) set_property(TARGET ${VIEWER_BINARY_NAME} PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") -endif (BUGSPLAT_DB) +endif (USE_BUGSPLAT) # add package files file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST @@ -2018,11 +2016,11 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLAPPEARANCE_LIBRARIES} ) -if (BUGSPLAT_DB) +if (USE_BUGSPLAT) target_link_libraries(${VIEWER_BINARY_NAME} ${BUGSPLAT_LIBRARIES} ) -endif (BUGSPLAT_DB) +endif (USE_BUGSPLAT) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") @@ -2206,7 +2204,7 @@ endif (INSTALL) # Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE) - if (NOT BUGSPLAT_DB) + if (NOT USE_BUGSPLAT) # Breakpad symbol-file generation set(SYMBOL_SEARCH_DIRS "") if (WINDOWS) @@ -2261,7 +2259,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}") endif (WINDOWS OR LINUX) - else (NOT BUGSPLAT_DB) + else (NOT USE_BUGSPLAT) # BugSplat symbol-file generation if (WINDOWS) # Just pack up a tarball containing only the .pdb file for the @@ -2345,9 +2343,9 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE if (LINUX) # TBD endif (LINUX) - endif (NOT BUGSPLAT_DB) + endif (NOT USE_BUGSPLAT) - # for both BUGSPLAT_DB and Breakpad + # for both Bugsplat and Breakpad add_dependencies(llpackage generate_symbols) endif () diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1fda07edd6..f9ee22d20a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -719,14 +719,14 @@ LLAppViewer::LLAppViewer() // from the previous viewer run between this constructor call and the // init() call, which will overwrite the static_debug_info.log file for // THIS run. So setDebugFileNames() early. -#if LL_BUGSPLAT +# ifdef LL_BUGSPLAT // MAINT-8917: don't create a dump directory just for the // static_debug_info.log file std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); -#else // ! LL_BUGSPLAT +# else // ! LL_BUGSPLAT // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); -#endif // ! LL_BUGSPLAT +# endif // ! LL_BUGSPLAT mDumpPath = logdir; setMiniDumpDir(logdir); setDebugFileNames(logdir); @@ -751,6 +751,16 @@ public: } }; +namespace { +// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide +// this little helper function. +void fast_exit(int rc) +{ + _exit(rc); +} + + +} bool LLAppViewer::init() { @@ -790,6 +800,18 @@ bool LLAppViewer::init() initMaxHeapSize() ; LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); + // Although initLoggingAndGetLastDuration() is the right place to mess with + // overrideCrashOnError(), we can't query gSavedSettings until after + // initConfiguration(). + S32 rc(gSavedSettings.getS32("QAModeTermCode")); + if (rc >= 0) + { + // QAModeTermCode set, terminate with that rc on LL_ERRS. Use + // fast_exit() rather than exit() because normal cleanup depends too + // much on successful startup! + LLError::overrideCrashOnError(boost::bind(fast_exit, rc)); + } + mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // Initialize the non-LLCurl libcurl library. Should be called @@ -2096,9 +2118,6 @@ bool LLAppViewer::cleanup() return true; } - gDebugInfo["FatalMessage"] = error_string; - LLAppViewer::instance()->writeDebugInfo(); - bool LLAppViewer::initThreads() { static const bool enable_threads = true; @@ -2133,6 +2152,24 @@ bool LLAppViewer::initThreads() return true; } +#ifndef LL_BUGSPLAT +void errorCallback(const std::string &error_string) +{ +#ifndef LL_RELEASE_FOR_DOWNLOAD + OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); +#endif + + //Set the ErrorActivated global so we know to create a marker file + gLLErrorActivated = true; + + gDebugInfo["FatalMessage"] = error_string; + // We're not already crashing -- we simply *intend* to crash. Since we + // haven't actually trashed anything yet, we can afford to write the whole + // static info file. + LLAppViewer::instance()->writeDebugInfo(); +} +#endif // ! LL_BUGSPLAT + void LLAppViewer::initLoggingAndGetLastDuration() { // @@ -2889,7 +2926,6 @@ bool LLAppViewer::initWindow() // Need to load feature table before cheking to start watchdog. bool use_watchdog = false; int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); - if (watchdog_enabled_setting == -1) { use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); @@ -3352,10 +3388,19 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["MainloopThreadID"] = (S32)thread_id; #endif +#ifndef LL_BUGSPLAT + // "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) // to try to distinguish crashes from freezes gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false; gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); +#endif // ! LL_BUGSPLAT // 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 diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 2f3e5db84f..0a01113224 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -145,10 +145,10 @@ void LLWatchdogTimeout::ping(const std::string& state) } // LLWatchdog -LLWatchdog::LLWatchdog() : - mSuspectsAccessMutex(), - mTimer(NULL), - mLastClockCount(0) +LLWatchdog::LLWatchdog() + :mSuspectsAccessMutex() + ,mTimer(NULL) + ,mLastClockCount(0) { } diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 8344cead57..7ac1f1db23 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -13,7 +13,7 @@ include(LLXML) include(Linking) include(Tut) include(LLAddBuildTest) - +include(bugsplat) include(GoogleMock) include_directories( @@ -82,6 +82,10 @@ list(APPEND test_SOURCE_FILES ${test_HEADER_FILES}) add_executable(lltest ${test_SOURCE_FILES}) +if (USE_BUGSPLAT) + set_target_properties(lltest PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") +endif (USE_BUGSPLAT) + target_link_libraries(lltest ${LLDATABASE_LIBRARIES} ${LLINVENTORY_LIBRARIES} diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 125de72b79..5dabcbbc58 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -75,7 +75,10 @@ #include -void wouldHaveCrashed(const std::string& message); +void wouldHaveCrashed(const std::string& message) +{ + tut::fail("fatal error message: " + message); +} namespace tut { @@ -506,11 +509,6 @@ void stream_groups(std::ostream& s, const char* app) } } -void wouldHaveCrashed(const std::string& message) -{ - tut::fail("fatal error message: " + message); -} - static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL; int main(int argc, char **argv) -- cgit v1.3 From e86c0b3d0fbc5f91090241be959ef19bfffd8636 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 5 Mar 2019 04:44:29 -0500 Subject: fix error message reporting? --- indra/llcommon/llerror.cpp | 18 +++++++-------- indra/llcommon/llerror.h | 6 +++-- indra/llcommon/llerrorcontrol.h | 11 ++++++--- indra/llcommon/tests/llerror_test.cpp | 8 +++++-- indra/llcommon/tests/wrapllerrs.h | 8 +++---- indra/newview/llappviewer.cpp | 43 ++++++++++++----------------------- indra/newview/llappviewermacosx.cpp | 6 ++--- indra/test/test.cpp | 7 +++--- 8 files changed, 51 insertions(+), 56 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 77d7fe1b24..6fa9e590cb 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -719,7 +719,7 @@ namespace LLError commonInit(user_dir, app_dir, log_to_stderr); } - void overrideCrashOnError(const FatalFunction& fatal_function) + void setFatalHandler(const FatalFunction& fatal_function) { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); s->mCrashFunction = fatal_function; @@ -1306,12 +1306,12 @@ namespace LLError return ; } - bool Log::flush(std::ostringstream* out, const CallSite& site) + ErrCrashHandlerResult Log::flush(std::ostringstream* out, const CallSite& site) { LLMutexTrylock lock(&gLogMutex,5); if (!lock.isLocked()) { - return false; // because this wasn't logged, it cannot be fatal + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } // If we hit a logging request very late during shutdown processing, @@ -1319,7 +1319,7 @@ namespace LLError // DO NOT resurrect them. if (Settings::wasDeleted() || Globals::wasDeleted()) { - return false; // because this wasn't logged, it cannot be fatal + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } Globals* g = Globals::getInstance(); @@ -1353,7 +1353,7 @@ namespace LLError } else { - return false; // because this wasn't logged, it cannot be fatal + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } } else @@ -1369,20 +1369,18 @@ namespace LLError if (site.mLevel == LEVEL_ERROR) { - g->mFatalMessage = message; if (s->mCrashFunction) { - s->mCrashFunction(message); - return false; // because an override is in effect + return s->mCrashFunction(message); } else { - return true; // calling macro should crash + return ERR_CRASH; // calling macro should crash } } else { - return false; // not ERROR, so do not crash + return ERR_DO_NOT_CRASH; // not ERROR, so do not crash } } } diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 07aa5c6f8b..2a73ccb36a 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -194,6 +194,8 @@ namespace LLError struct CallSite; + enum ErrCrashHandlerResult { ERR_DO_NOT_CRASH, ERR_CRASH }; + class LL_COMMON_API Log { public: @@ -203,7 +205,7 @@ namespace LLError static void flush(std::ostringstream* out, char* message); // returns false iff the calling macro should crash - static bool flush(std::ostringstream*, const CallSite&); + static ErrCrashHandlerResult flush(std::ostringstream*, const CallSite&); static std::string demangle(const char* mangled); }; @@ -386,7 +388,7 @@ volatile extern int* gCauseCrash; #define LL_ENDL \ LLError::End(); \ - if (LLError::Log::flush(_out, _site)) \ + if (LLError::ERR_CRASH == LLError::Log::flush(_out, _site)) \ LLERROR_CRASH \ } \ } while(0) diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index af46430f74..2fa220ba5a 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -93,16 +93,21 @@ namespace LLError Control functions. */ - typedef boost::function FatalFunction; + // A FatalFunction is called if set using setFatalHandler; its return controls + // whether or not the calling error logging code should crash. + // ERR_DO_NOT_CRASH should be used only in test code. + typedef boost::function FatalFunction; + /// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code - LL_COMMON_API void overrideCrashOnError(const FatalFunction&); + LL_COMMON_API void setFatalHandler(const FatalFunction&); // The fatal function will be called when an message of LEVEL_ERROR // is logged. Note: supressing a LEVEL_ERROR message from being logged // (by, for example, setting a class level to LEVEL_NONE), will keep // the that message from causing the fatal funciton to be invoked. + // The - /// Undo the effect of the overrideCrashOnError above + /// Undo the effect of the setFatalHandler above LL_COMMON_API void restoreCrashOnError(); LL_COMMON_API std::string getFatalMessage(); diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 2f8923d2de..9dcb5c145f 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -70,7 +70,11 @@ namespace namespace { static bool fatalWasCalled; - void fatalCall(const std::string&) { fatalWasCalled = true; } + LLError::ErrCrashHandlerResult fatalCall(const std::string&) + { + fatalWasCalled = true; + return LLError::ERR_DO_NOT_CRASH; + } } namespace tut @@ -120,7 +124,7 @@ namespace tut mPriorErrorSettings = LLError::saveAndResetSettings(); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - LLError::overrideCrashOnError(fatalCall); + LLError::setFatalHandler(fatalCall); LLError::addRecorder(mRecorder); } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index fedc17dbe9..a412e12a04 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -46,7 +46,7 @@ // statically reference the function in test.cpp... it's short, we could // replicate, but better to reuse -extern void wouldHaveCrashed(const std::string& message); +extern LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message); struct WrapLLErrs { @@ -57,7 +57,7 @@ struct WrapLLErrs :mPriorErrorSettings(LLError::saveAndResetSettings()) { // Make LL_ERRS call our own operator() method - LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1)); + LLError::setFatalHandler(boost::bind(&WrapLLErrs::operator(), this, _1)); } ~WrapLLErrs() @@ -71,7 +71,7 @@ struct WrapLLErrs FatalException(const std::string& what): LLException(what) {} }; - void operator()(const std::string& message) + LLError::ErrCrashHandlerResult operator()(const std::string& message) { // Save message for later in case consumer wants to sense the result directly error = message; @@ -201,7 +201,7 @@ public: mOldSettings(LLError::saveAndResetSettings()), mRecorder(new CaptureLogRecorder()) { - LLError::overrideCrashOnError(wouldHaveCrashed); + LLError::setFatalHandler(wouldHaveCrashed); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f9ee22d20a..8b9f9085b1 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -751,16 +751,7 @@ public: } }; -namespace { -// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide -// this little helper function. -void fast_exit(int rc) -{ - _exit(rc); -} - - -} +static S32 sQAModeTermCode = 0; // set from QAModeTermCode to specify exit code for LL_ERRS bool LLAppViewer::init() { @@ -800,17 +791,8 @@ bool LLAppViewer::init() initMaxHeapSize() ; LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); - // Although initLoggingAndGetLastDuration() is the right place to mess with - // overrideCrashOnError(), we can't query gSavedSettings until after - // initConfiguration(). - S32 rc(gSavedSettings.getS32("QAModeTermCode")); - if (rc >= 0) - { - // QAModeTermCode set, terminate with that rc on LL_ERRS. Use - // fast_exit() rather than exit() because normal cleanup depends too - // much on successful startup! - LLError::overrideCrashOnError(boost::bind(fast_exit, rc)); - } + // if a return code is set for error exit, save it here for use in fatalErrorHandler + sQAModeTermCode = gSavedSettings.getS32("QAModeTermCode"); mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); @@ -2152,8 +2134,7 @@ bool LLAppViewer::initThreads() return true; } -#ifndef LL_BUGSPLAT -void errorCallback(const std::string &error_string) +LLError::ErrCrashHandlerResult fatalErrorHandler(const std::string &error_string) { #ifndef LL_RELEASE_FOR_DOWNLOAD OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); @@ -2167,8 +2148,15 @@ void errorCallback(const std::string &error_string) // haven't actually trashed anything yet, we can afford to write the whole // static info file. LLAppViewer::instance()->writeDebugInfo(); + + if (sQAModeTermCode) + { + _exit(sQAModeTermCode); + return LLError::ERR_DO_NOT_CRASH; // notreached + } + + return LLError::ERR_CRASH; } -#endif // ! LL_BUGSPLAT void LLAppViewer::initLoggingAndGetLastDuration() { @@ -2178,6 +2166,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ); + LLError::setFatalHandler(fatalErrorHandler); // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, @@ -3728,12 +3717,8 @@ void LLAppViewer::processMarkerFiles() else if (marker_is_same_version) { // the file existed, is ours, and matched our version, so we can report on what it says - LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL; -# if LL_BUGSPLAT + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL; gLastExecEvent = LAST_EXEC_OTHER_CRASH; -# else - gLastExecEvent = LAST_EXEC_FROZE; -# endif } else { diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 3111540a13..9c2e6eadca 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -188,17 +188,17 @@ CrashMetadataSingleton::CrashMetadataSingleton() LLSD info; if (! static_file.is_open()) { - LL_INFOS() << "Can't open '" << staticDebugPathname + LL_WARNS() << "Can't open '" << staticDebugPathname << "'; no metadata about previous run" << LL_ENDL; } else if (! LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED)) { - LL_INFOS() << "Can't parse '" << staticDebugPathname + LL_WARNS() << "Can't parse '" << staticDebugPathname << "'; no metadata about previous run" << LL_ENDL; } else { - LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL; + LL_INFOS() << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL; logFilePathname = get_metadata(info, "SLLog"); userSettingsPathname = get_metadata(info, "SettingsFilename"); OSInfo = get_metadata(info, "OSInfo"); diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 5dabcbbc58..4f966aede8 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -75,9 +75,10 @@ #include -void wouldHaveCrashed(const std::string& message) +LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message) { tut::fail("fatal error message: " + message); + return LLError::ERR_DO_NOT_CRASH; } namespace tut @@ -149,7 +150,7 @@ public: mOldSettings(LLError::saveAndResetSettings()), mRecorder(new RecordToTempFile(pool)) { - LLError::overrideCrashOnError(wouldHaveCrashed); + LLError::setFatalHandler(wouldHaveCrashed); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } @@ -530,7 +531,7 @@ int main(int argc, char **argv) LLError::initForApplication(".", ".", false /* do not log to stderr */); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); } - LLError::overrideCrashOnError(wouldHaveCrashed); + LLError::setFatalHandler(wouldHaveCrashed); std::string test_app_name(argv[0]); std::string test_log = test_app_name + ".log"; LLFile::remove(test_log); -- cgit v1.3 From 07870a9ebb17e7a31df276f4ac2d8f52fec2a3b0 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 5 Mar 2019 13:57:02 -0500 Subject: rename crash handler to hook, and make them chainable by putting back the get and documenting it --- indra/llcommon/llerror.cpp | 18 +++++++++--------- indra/llcommon/llerror.h | 6 +++--- indra/llcommon/llerrorcontrol.h | 26 ++++++++++++++------------ indra/llcommon/llleap.cpp | 32 +++++++++++++++++++++++++++++++- indra/llcommon/tests/llerror_test.cpp | 4 ++-- indra/llcommon/tests/wrapllerrs.h | 23 +++++++++++++---------- indra/newview/llappviewer.cpp | 4 ++-- indra/test/test.cpp | 6 +++--- 8 files changed, 77 insertions(+), 42 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 6fa9e590cb..5f3edf7f84 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -483,7 +483,7 @@ namespace LLError LevelMap mTagLevelMap; std::map mUniqueLogMessages; - LLError::FatalFunction mCrashFunction; + LLError::FatalHook mFatalHook; LLError::TimeFunction mTimeFunction; Recorders mRecorders; @@ -523,7 +523,7 @@ namespace LLError mFileLevelMap(), mTagLevelMap(), mUniqueLogMessages(), - mCrashFunction(NULL), + mFatalHook(NULL), mTimeFunction(NULL), mRecorders(), mFileRecorder(), @@ -719,16 +719,16 @@ namespace LLError commonInit(user_dir, app_dir, log_to_stderr); } - void setFatalHandler(const FatalFunction& fatal_function) + void setFatalHook(const FatalHook& fatal_hook) { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - s->mCrashFunction = fatal_function; + s->mFatalHook = fatal_hook; } - void restoreCrashOnError() + FatalHook getFatalHook() { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - s->mCrashFunction = NULL; + return s->mFatalHook; } std::string getFatalMessage() @@ -1306,7 +1306,7 @@ namespace LLError return ; } - ErrCrashHandlerResult Log::flush(std::ostringstream* out, const CallSite& site) + ErrFatalHookResult Log::flush(std::ostringstream* out, const CallSite& site) { LLMutexTrylock lock(&gLogMutex,5); if (!lock.isLocked()) @@ -1369,9 +1369,9 @@ namespace LLError if (site.mLevel == LEVEL_ERROR) { - if (s->mCrashFunction) + if (s->mFatalHook) { - return s->mCrashFunction(message); + return s->mFatalHook(message); } else { diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 2a73ccb36a..6bdb2e852f 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -194,7 +194,7 @@ namespace LLError struct CallSite; - enum ErrCrashHandlerResult { ERR_DO_NOT_CRASH, ERR_CRASH }; + enum ErrFatalHookResult { ERR_DO_NOT_CRASH, ERR_CRASH }; class LL_COMMON_API Log { @@ -205,7 +205,7 @@ namespace LLError static void flush(std::ostringstream* out, char* message); // returns false iff the calling macro should crash - static ErrCrashHandlerResult flush(std::ostringstream*, const CallSite&); + static ErrFatalHookResult flush(std::ostringstream*, const CallSite&); static std::string demangle(const char* mangled); }; @@ -272,7 +272,7 @@ namespace LLError //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. + //LLCallStacks is designed not to be thread-safe. //so try not to use it in multiple parallel threads at same time. //Used in a single thread at a time is fine. class LL_COMMON_API LLCallStacks diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 2fa220ba5a..e7c5241cc9 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -93,22 +93,24 @@ namespace LLError Control functions. */ - // A FatalFunction is called if set using setFatalHandler; its return controls + // A FatalHook is called if set using setFatalHook; its return controls // whether or not the calling error logging code should crash. // ERR_DO_NOT_CRASH should be used only in test code. - typedef boost::function FatalFunction; - - - /// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code - LL_COMMON_API void setFatalHandler(const FatalFunction&); - // The fatal function will be called when an message of LEVEL_ERROR + typedef boost::function FatalHook; + + /// Supplement and control the default behavior of crashing on LL_ERRS + /// This may be used to suppress crashes only in test code; + /// otherwise, the FatalHook should always either return + /// the result from the previous hook (see getFatalHook below), + /// or return LLError::ERR_CRASH + LL_COMMON_API void setFatalHook(const FatalHook& fatal_hook); + // The fatal_hook function will be called when an message of LEVEL_ERROR // is logged. Note: supressing a LEVEL_ERROR message from being logged - // (by, for example, setting a class level to LEVEL_NONE), will keep - // the that message from causing the fatal funciton to be invoked. - // The + // (by, for example, setting a class level to LEVEL_NONE), will also + // prevent the fatal_hook being called and the resulting deliberate crash - /// Undo the effect of the setFatalHandler above - LL_COMMON_API void restoreCrashOnError(); + /// Retrieve the previously-set FatalHook + LL_COMMON_API FatalHook getFatalHook(); LL_COMMON_API std::string getFatalMessage(); // Retrieve the message last passed to LL_ERRS, if any diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index bf20c87c89..161d25bc34 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -59,7 +59,7 @@ public: // pump name -- so it should NOT need tweaking for uniqueness. mReplyPump(LLUUID::generateNewID().asString()), mExpect(0), - + mPrevFatalHook(LLError::getFatalHook()), // Instantiate a distinct LLLeapListener for this plugin. (Every // plugin will want its own collection of managed listeners, etc.) // Pass it a callback to our connect() method, so it can send events @@ -145,6 +145,9 @@ public: mStderrConnection = childerr.getPump() .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1)); + // For our lifespan, intercept any LL_ERRS so we can notify plugin + LLError::setFatalHook(boost::bind(&LLLeapImpl::fatalHook, this, _1)); + // Send child a preliminary event reporting our own reply-pump name -- // which would otherwise be pretty tricky to guess! wstdin(mReplyPump.getName(), @@ -159,6 +162,8 @@ public: virtual ~LLLeapImpl() { LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL; + // Restore original FatalHook + LLError::setFatalHook(mPrevFatalHook); } // Listener for failed launch attempt @@ -372,6 +377,30 @@ public: return false; } + LLError::ErrFatalHookResult fatalHook(const std::string& error) + { + // Notify plugin + LLSD event; + event["type"] = "error"; + event["error"] = error; + mReplyPump.post(event); + + // All the above really accomplished was to buffer the serialized + // event in our WritePipe. Have to pump mainloop a couple times to + // really write it out there... but time out in case we can't write. + LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + LLSD nop; + F64 until = (LLTimer::getElapsedSeconds() + 2).value(); + while (childin.size() && LLTimer::getElapsedSeconds() < until) + { + mainloop.post(nop); + } + + // forward the call to the previous FatalHook, default to crashing if there isn't one + return mPrevFatalHook ? mPrevFatalHook(error) : LLError::ERR_CRASH; + } + private: /// We always want to listen on mReplyPump with wstdin(); under some /// circumstances we'll also echo other LLEventPumps to the plugin. @@ -392,6 +421,7 @@ private: mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection; boost::scoped_ptr mBlocker; LLProcess::ReadPipe::size_type mExpect; + LLError::FatalHook mPrevFatalHook; boost::scoped_ptr mListener; }; diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 9dcb5c145f..9895abc1f3 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -70,7 +70,7 @@ namespace namespace { static bool fatalWasCalled; - LLError::ErrCrashHandlerResult fatalCall(const std::string&) + LLError::ErrFatalHookResult fatalHook(const std::string&) { fatalWasCalled = true; return LLError::ERR_DO_NOT_CRASH; @@ -124,7 +124,7 @@ namespace tut mPriorErrorSettings = LLError::saveAndResetSettings(); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); - LLError::setFatalHandler(fatalCall); + LLError::setFatalHook(fatalHook); LLError::addRecorder(mRecorder); } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index a412e12a04..a6c44d5fdd 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -46,7 +46,7 @@ // statically reference the function in test.cpp... it's short, we could // replicate, but better to reuse -extern LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message); +extern LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message); struct WrapLLErrs { @@ -55,14 +55,15 @@ struct WrapLLErrs // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the // console output of successful tests, potentially confusing things. :mPriorErrorSettings(LLError::saveAndResetSettings()) + ,mPriorFatalHook(LLError::getFatalHook()) { // Make LL_ERRS call our own operator() method - LLError::setFatalHandler(boost::bind(&WrapLLErrs::operator(), this, _1)); + LLError::setFatalHook(boost::bind(&WrapLLErrs::operator(), this, _1)); } ~WrapLLErrs() { - LLError::restoreCrashOnError(); + LLError::setFatalHook(mPriorFatalHook); LLError::restoreSettings(mPriorErrorSettings); } @@ -71,7 +72,7 @@ struct WrapLLErrs FatalException(const std::string& what): LLException(what) {} }; - LLError::ErrCrashHandlerResult operator()(const std::string& message) + LLError::ErrFatalHookResult operator()(const std::string& message) { // Save message for later in case consumer wants to sense the result directly error = message; @@ -107,7 +108,7 @@ struct WrapLLErrs std::string error; LLError::SettingsStoragePtr mPriorErrorSettings; - LLError::FatalFunction mPriorFatal; + LLError::FatalHook mPriorFatalHook; }; /** @@ -197,11 +198,12 @@ public: // with that output. If it turns out that saveAndResetSettings() has // some bad effect, give up and just let the DEBUG level log messages // display. - : boost::noncopyable(), - mOldSettings(LLError::saveAndResetSettings()), - mRecorder(new CaptureLogRecorder()) + : boost::noncopyable() + , mOldSettings(LLError::saveAndResetSettings()) + , mPriorFatalHook(LLError::getFatalHook()) + , mRecorder(new CaptureLogRecorder()) { - LLError::setFatalHandler(wouldHaveCrashed); + LLError::setFatalHook(wouldHaveCrashed); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } @@ -210,7 +212,7 @@ public: { LLError::removeRecorder(mRecorder); LLError::restoreSettings(mOldSettings); - LLError::restoreCrashOnError(); + LLError::setFatalHook(mPriorFatalHook); } /// Don't assume the message we want is necessarily the LAST log message @@ -228,6 +230,7 @@ public: private: LLError::SettingsStoragePtr mOldSettings; + LLError::FatalHook mPriorFatalHook; LLError::RecorderPtr mRecorder; }; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8b9f9085b1..8616fe7c76 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2134,7 +2134,7 @@ bool LLAppViewer::initThreads() return true; } -LLError::ErrCrashHandlerResult fatalErrorHandler(const std::string &error_string) +LLError::ErrFatalHookResult fatalErrorHook(const std::string &error_string) { #ifndef LL_RELEASE_FOR_DOWNLOAD OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); @@ -2166,7 +2166,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ); - LLError::setFatalHandler(fatalErrorHandler); + LLError::setFatalHook(fatalErrorHook); // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 4f966aede8..52ac855d9f 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -75,7 +75,7 @@ #include -LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message) +LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message) { tut::fail("fatal error message: " + message); return LLError::ERR_DO_NOT_CRASH; @@ -150,7 +150,7 @@ public: mOldSettings(LLError::saveAndResetSettings()), mRecorder(new RecordToTempFile(pool)) { - LLError::setFatalHandler(wouldHaveCrashed); + LLError::setFatalHook(wouldHaveCrashed); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } @@ -531,7 +531,7 @@ int main(int argc, char **argv) LLError::initForApplication(".", ".", false /* do not log to stderr */); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); } - LLError::setFatalHandler(wouldHaveCrashed); + LLError::setFatalHook(wouldHaveCrashed); std::string test_app_name(argv[0]); std::string test_log = test_app_name + ".log"; LLFile::remove(test_log); -- cgit v1.3 From 1e98a607d08019f66ae878e4cb247e850a7443cf Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 4 Jun 2019 10:06:43 -0400 Subject: try putting fatal message into dynamic crash data --- indra/newview/llappviewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8616fe7c76..0e97ed5a47 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3388,7 +3388,7 @@ void LLAppViewer::writeSystemInfo() // "CrashNotHandled" is obsolete; it used (not very successsfully) // to try to distinguish crashes from freezes gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false; - gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); + gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage(); #endif // ! LL_BUGSPLAT // Insert crash host url (url to post crash log to) if configured. This insures -- cgit v1.3 From e711376cc75a51973291d1730467c0b6e3a74226 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 5 Jun 2019 14:27:48 -0400 Subject: assorted cleanup --- indra/llcommon/llapp.cpp | 5 +++++ indra/newview/CMakeLists.txt | 2 +- indra/newview/llappdelegate-objc.mm | 2 ++ indra/newview/llappviewer.cpp | 10 ++-------- indra/newview/llappviewerwin32.cpp | 3 +-- indra/newview/llviewerwindow.cpp | 3 ++- 6 files changed, 13 insertions(+), 12 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 421af3006e..34c969437b 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -526,7 +526,12 @@ void LLApp::setupErrorHandling(bool second_instance) #endif // LL_LINUX #endif // ! LL_WINDOWS + +#ifdef LL_BUGSPLAT + // do not start our own error thread +#else // ! LL_BUGSPLAT startErrorThread(); +#endif } void LLApp::startErrorThread() diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bbfa838827..fd520d2c6f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1729,7 +1729,7 @@ endif (SDL_FOUND) if (USE_BUGSPLAT) set_property(TARGET ${VIEWER_BINARY_NAME} - PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT") + PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}") endif (USE_BUGSPLAT) # add package files diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 47fde299c7..30bfe1f439 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -66,6 +66,7 @@ constructViewer(); #if defined(LL_BUGSPLAT) + infos("bugsplat setup"); // Engage BugsplatStartupManager *before* calling initViewer() to handle // any crashes during initialization. // https://www.bugsplat.com/docs/platforms/os-x#initialization @@ -74,6 +75,7 @@ [BugsplatStartupManager sharedManager].delegate = self; [[BugsplatStartupManager sharedManager] start]; #endif + infos("post-bugsplat setup"); frameTimer = nil; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0e97ed5a47..35f9d7f4fd 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3386,9 +3386,8 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; #else // LL_BUGSPLAT // "CrashNotHandled" is obsolete; it used (not very successsfully) - // to try to distinguish crashes from freezes + // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false; - gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage(); #endif // ! LL_BUGSPLAT // Insert crash host url (url to post crash log to) if configured. This insures @@ -3617,7 +3616,7 @@ void LLAppViewer::handleViewerCrash() if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]); - gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage(); + gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); // Close the debug file pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead. @@ -5476,11 +5475,6 @@ void LLAppViewer::pauseMainloopTimeout() void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs) { -// if(!restoreErrorTrap()) -// { -// LL_WARNS() << "!!!!!!!!!!!!! Its an error trap!!!!" << state << LL_ENDL; -// } - if(mMainloopTimeout) { if(secs < 0.0f) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index d208e135bb..6a6cc225d4 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -802,8 +802,7 @@ bool LLAppViewerWin32::beingDebugged() bool LLAppViewerWin32::restoreErrorTrap() { - return true; - //return LLWinDebug::checkExceptionHandler(); + return false; } void LLAppViewerWin32::initCrashReporting(bool reportFreeze) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c214984e1d..b0f5b550e6 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1791,7 +1791,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) if (!LLAppViewer::instance()->restoreErrorTrap()) { - LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL; + // this always happens, so downgrading it to INFO + LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL; } const bool do_not_enforce = false; -- cgit v1.3 From d0619f8e476c1c5118ae926dfe1746f1dda986d8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 24 Sep 2019 14:27:21 -0400 Subject: improve fatal hook logging --- indra/llcommon/llerror.cpp | 4 ++-- indra/llcommon/llleap.cpp | 2 ++ indra/newview/llappviewer.cpp | 7 ++++++- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index da68117ff5..df8443bd7a 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -723,13 +723,13 @@ namespace LLError { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); s->mFatalHook = fatal_hook; - LL_DEBUGS("FatalHook") << "set fatal hook to " << fatal_hook << LL_ENDL; + LL_DEBUGS("FatalHook") << "set fatal hook to " << reinterpret_cast(fatal_hook) << LL_ENDL; } FatalHook getFatalHook() { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - LL_DEBUGS("FatalHook") << "read fatal hook " << s->mFatalHook << LL_ENDL; + LL_DEBUGS("FatalHook") << "read fatal hook " << reinterpret_cast(s->mFatalHook) << LL_ENDL; return s->mFatalHook; } diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 161d25bc34..bb32c73d04 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -67,6 +67,7 @@ public: // this class or method name. mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2))) { + LL_DEBUGS("FatalHook") << "previous fatal hook was " <(mPrevFatalHook) << LL_ENDL; // Rule out unpopulated Params block if (! cparams.executable.isProvided()) { @@ -398,6 +399,7 @@ public: } // forward the call to the previous FatalHook, default to crashing if there isn't one + LL_DEBUGS("FatalHook") << "end" << LL_ENDL; return mPrevFatalHook ? mPrevFatalHook(error) : LLError::ERR_CRASH; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 35f9d7f4fd..9258d1a219 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2166,7 +2166,8 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ); - LLError::setFatalHook(fatalErrorHook); + + // TBD fatal hook belongs here // Remove the last ".old" log file. std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, @@ -2228,6 +2229,10 @@ void LLAppViewer::initLoggingAndGetLastDuration() { LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; } + + // TBD - temporary location for fatal hook (should be above, but for now it logs...) + LLError::setFatalHook(fatalErrorHook); + } bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, -- cgit v1.3 From a45ca18ff8160bc3edc584d6516ca019dd6c6275 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Wed, 25 Sep 2019 12:59:20 -0400 Subject: when using bugsplat, do not catch SIGABRT; also, fix signal setting in Mac (broken macro) --- indra/llcommon/llapp.cpp | 5 +++++ indra/newview/llappviewer.cpp | 2 +- indra/newview/llappviewermacosx.cpp | 9 +++++---- 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 34c969437b..27960371f1 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -779,7 +779,9 @@ void setup_signals() act.sa_flags = SA_SIGINFO; // Synchronous signals +# ifndef LL_BUGSPLAT sigaction(SIGABRT, &act, NULL); +# endif sigaction(SIGALRM, &act, NULL); sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); @@ -816,7 +818,9 @@ void clear_signals() act.sa_flags = SA_SIGINFO; // Synchronous signals +# ifndef LL_BUGSPLAT sigaction(SIGABRT, &act, NULL); +# endif sigaction(SIGALRM, &act, NULL); sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); @@ -869,6 +873,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) return; case SIGABRT: + // Note that this handler is not set for SIGABRT when using Bugsplat // Abort just results in termination of the app, no funky error handling. if (LLApp::sLogInSignal) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9258d1a219..8009a9c117 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2231,8 +2231,8 @@ void LLAppViewer::initLoggingAndGetLastDuration() } // TBD - temporary location for fatal hook (should be above, but for now it logs...) + LL_DEBUGS("FatalHook") << "initial setting of default fatalhook" << LL_ENDL; LLError::setFatalHook(fatalErrorHook); - } bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 4a519b944b..efa1da054c 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -333,11 +333,12 @@ bool LLAppViewerMacOSX::restoreErrorTrap() unsigned int reset_count = 0; -#define SET_SIG(S) sigaction(SIGABRT, &act, &old_act); \ - if(act.sa_sigaction != old_act.sa_sigaction) \ - ++reset_count; +#define SET_SIG(SIGNAL) sigaction(SIGNAL, &act, &old_act); \ + if(act.sa_sigaction != old_act.sa_sigaction) ++reset_count; // Synchronous signals - SET_SIG(SIGABRT) +# ifndef LL_BUGSPLAT + SET_SIG(SIGABRT) // let bugsplat catch this +# endif SET_SIG(SIGALRM) SET_SIG(SIGBUS) SET_SIG(SIGFPE) -- cgit v1.3 From 88746478583711951d04a3ea709ccf1667ddf535 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 3 Mar 2021 19:33:02 +0200 Subject: SL-14940 Fixed ignoring custom cache path fix by Ansariel (https://vcs.firestormviewer.org/phoenix-firestorm/changeset/dace23b988af90a65ef57b0b9f540fc48d439dc3) --- doc/contributions.txt | 1 + indra/newview/llappviewer.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/doc/contributions.txt b/doc/contributions.txt index de783330c6..5baf717a06 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -227,6 +227,7 @@ Ansariel Hiller SL-13858 SL-13697 SL-14939 + SL-14940 Aralara Rajal Arare Chantilly CHUIBUG-191 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ea0b950e62..0dc2c7d326 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4132,8 +4132,6 @@ bool LLAppViewer::initCache() const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100; const unsigned int disk_cache_bytes = disk_cache_mb * 1024 * 1024; const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo"); - const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); - LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); bool texture_cache_mismatch = false; if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) @@ -4181,6 +4179,9 @@ bool LLAppViewer::initCache() gSavedSettings.setString("CacheLocationTopFolder", ""); } + const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); + LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); + if (!read_only) { if (mPurgeCache) -- cgit v1.3 From 3067f56b1f1be6506b0bddd2889854ad7fdf4d8a Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 9 Mar 2021 21:57:32 +0200 Subject: Revert "SL-14940 Fixed ignoring custom cache path" This reverts commit 88746478583711951d04a3ea709ccf1667ddf535. --- doc/contributions.txt | 1 - indra/newview/llappviewer.cpp | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/doc/contributions.txt b/doc/contributions.txt index 5baf717a06..de783330c6 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -227,7 +227,6 @@ Ansariel Hiller SL-13858 SL-13697 SL-14939 - SL-14940 Aralara Rajal Arare Chantilly CHUIBUG-191 diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0dc2c7d326..ea0b950e62 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4132,6 +4132,8 @@ bool LLAppViewer::initCache() const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100; const unsigned int disk_cache_bytes = disk_cache_mb * 1024 * 1024; const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo"); + const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); + LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); bool texture_cache_mismatch = false; if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) @@ -4179,9 +4181,6 @@ bool LLAppViewer::initCache() gSavedSettings.setString("CacheLocationTopFolder", ""); } - const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); - LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info); - if (!read_only) { if (mPurgeCache) -- cgit v1.3 From 4076208a72dbcb36adbdfcca86a9fbcc12d2bda3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 10 Mar 2021 20:28:00 +0200 Subject: SL-14961 Bugsplat logging --- indra/newview/llappviewer.cpp | 27 ++++++++++++++++ indra/newview/llappviewer.h | 2 ++ indra/newview/llappviewerwin32.cpp | 36 ++++++++++++++++++---- indra/newview/llviewermenu.cpp | 32 +++++++++++++++++++ indra/newview/skins/default/xui/en/menu_viewer.xml | 12 ++++++++ 5 files changed, 103 insertions(+), 6 deletions(-) (limited to 'indra/newview/llappviewer.cpp') 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 @@ -2437,6 +2437,18 @@ function="World.EnvPreset" + + + + + + -- cgit v1.3 From ed98ebb8115bffc5cf78ec00e33adf2243c55f0d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Mar 2021 18:19:53 +0200 Subject: SL-14961 Coroutine crash was not reported to bugsplat --- indra/llcommon/llapp.h | 4 +++ indra/llcommon/llcoros.cpp | 58 +++++++++++++++++++++++++++----------- indra/llcommon/llcoros.h | 7 +++-- indra/newview/llappviewer.cpp | 2 +- indra/newview/llappviewerwin32.cpp | 10 +++++++ indra/newview/llappviewerwin32.h | 22 ++++++++------- 6 files changed, 72 insertions(+), 31 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 245c73e3a2..5fa91b8bf5 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -259,6 +259,10 @@ public: */ LLRunner& getRunner() { return mRunner; } +#ifdef LL_WINDOWS + virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { } +#endif + public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 262929006d..111c50af93 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -255,8 +255,21 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) { + // C++ exceptions were logged in toplevelTryWrapper, but not SEH + // log SEH exceptions here, to make sure it gets into bugsplat's + // report and because __try won't allow std::string operations + if (code != STATUS_MSC_EXCEPTION) + { + LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; + } + // Handle bugsplat here, since GetExceptionInformation() can only be + // called from within filter for __except(filter), not from __except's {} + // Bugsplat should get all exceptions, C++ and SEH + LLApp::instance()->reportCrashToBugsplat(exception_infop); + + // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -269,29 +282,29 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) } } -void LLCoros::winlevel(const callable_t& callable) +void LLCoros::winlevel(const std::string& name, const callable_t& callable) { __try { - callable(); + toplevelTryWrapper(name, callable); } - __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) { - // convert to C++ styled exception + // convert to C++ styled exception for handlers other than bugsplat // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + // + // in case of bugsplat this will get to exceptionTerminateHandler and + // looks like fiber will terminate application after that + char integer_string[512]; + sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); throw std::exception(integer_string); } } #endif -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) +void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -301,16 +314,12 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { -#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD - winlevel(callable); -#else callable(); -#endif } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -323,10 +332,25 @@ void LLCoros::toplevel(std::string name, callable_t callable) { // Any OTHER kind of uncaught exception will cause the viewer to // crash, hopefully informatively. - CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); + // to not modify callstack + throw; } } +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) +{ +#if LL_WINDOWS + // Can not use __try in functions that require unwinding, so use one more wrapper + winlevel(name, callable); +#else + toplevelTryWrapper(name, callable); +#endif +} + //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 38c2356c99..6c0bec3ef9 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -290,11 +290,12 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; - void toplevel(std::string name, callable_t callable); - struct CoroData; #if LL_WINDOWS - static void winlevel(const callable_t& callable); + void winlevel(const std::string& name, const callable_t& callable); #endif + void toplevelTryWrapper(const std::string& name, const callable_t& callable); + void toplevel(std::string name, callable_t callable); + struct CoroData; static CoroData& get_CoroData(const std::string& caller); S32 mStackSize; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a1d73acfa5..7c2f622abd 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5552,7 +5552,7 @@ void LLAppViewer::forceErrorDriverCrash() 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"); }); + LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw LLException("A deliberate crash from LLCoros"); }); } void LLAppViewer::forceErrorThreadCrash() diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index bb6156e209..ce36d3458e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -709,6 +709,16 @@ bool LLAppViewerWin32::cleanup() return result; } +void LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo) +{ +#if defined(LL_BUGSPLAT) + if (sBugSplatSender) + { + sBugSplatSender->createReport((EXCEPTION_POINTERS*)pExcepInfo); + } +#endif // LL_BUGSPLAT +} + void LLAppViewerWin32::initLoggingAndGetLastDuration() { LLAppViewer::initLoggingAndGetLastDuration(); diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index c5fae6a3a3..83ae875a15 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -40,20 +40,22 @@ public: // // Main application logic // - virtual bool init(); // Override to do application initialization - virtual bool cleanup(); + bool init() override; // Override to do application initialization + bool cleanup() override; + + void reportCrashToBugsplat(void* pExcepInfo) override; protected: - virtual void initLoggingAndGetLastDuration(); // Override to clean stack_trace info. - virtual void initConsole(); // Initialize OS level debugging console. - virtual bool initHardwareTest(); // Win32 uses DX9 to test hardware. - virtual bool initParseCommandLine(LLCommandLineParser& clp); + void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info. + void initConsole() override; // Initialize OS level debugging console. + bool initHardwareTest() override; // Win32 uses DX9 to test hardware. + bool initParseCommandLine(LLCommandLineParser& clp) override; - virtual bool beingDebugged(); - virtual bool restoreErrorTrap(); - virtual void initCrashReporting(bool reportFreeze); + bool beingDebugged() override; + bool restoreErrorTrap() override; + void initCrashReporting(bool reportFreeze) override; - virtual bool sendURLToOtherInstance(const std::string& url); + bool sendURLToOtherInstance(const std::string& url) override; std::string generateSerialNumber(); -- cgit v1.3 From c0f28ae36261cc31d6412c42c05d1b7719a2c04b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 18 Mar 2021 22:45:38 +0200 Subject: SL-14927 Some avatar names not resolving --- doc/contributions.txt | 5 +++-- indra/newview/llagent.cpp | 15 +++++++-------- indra/newview/llagent.h | 2 +- indra/newview/llappviewer.cpp | 7 +++---- indra/newview/llappviewer.h | 3 ++- indra/newview/llenvironment.cpp | 2 +- indra/newview/llviewerregion.cpp | 4 ++-- indra/newview/llviewerregion.h | 2 +- indra/newview/llwlhandlers.cpp | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/doc/contributions.txt b/doc/contributions.txt index bbdfaf655d..2b77b58222 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -263,10 +263,11 @@ Benja Kepler Benjamin Bigdipper Beq Janus BUG-227094 -Beth Walcher -Beq Janus SL-10288 SL-13583 + SL-14766 + SL-14927 +Beth Walcher Bezilon Kasei Biancaluce Robbiani CT-225 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 5c00cfc783..baf0acc94b 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -879,13 +879,12 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal } // static -void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id) +void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp) { - LLViewerRegion* region = gAgent.getRegion(); - if (region && region->getRegionID() == region_id) + if (regionp && regionp->getRegionID() == region_id) { - region->requestSimulatorFeatures(); - LLAppViewer::instance()->updateNameLookupUrl(); + regionp->requestSimulatorFeatures(); + LLAppViewer::instance()->updateNameLookupUrl(regionp); } } @@ -936,7 +935,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (regionp->capabilitiesReceived()) { regionp->requestSimulatorFeatures(); - LLAppViewer::instance()->updateNameLookupUrl(); + LLAppViewer::instance()->updateNameLookupUrl(regionp); } else { @@ -962,11 +961,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp) if (regionp->capabilitiesReceived()) { - LLAppViewer::instance()->updateNameLookupUrl(); + LLAppViewer::instance()->updateNameLookupUrl(regionp); } else { - regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) {LLAppViewer::instance()->updateNameLookupUrl(); }); + regionp->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id, LLViewerRegion* regionp) {LLAppViewer::instance()->updateNameLookupUrl(regionp); }); } } diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index d46c99db8c..f5ca42af5b 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -254,7 +254,7 @@ public: boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t); private: - static void capabilityReceivedCallback(const LLUUID ®ion_id); + static void capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp); typedef boost::signals2::signal parcel_changed_signal_t; parcel_changed_signal_t mParcelChangedSignal; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7c2f622abd..fe2da2f989 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5226,10 +5226,9 @@ void LLAppViewer::sendLogoutRequest() } } -void LLAppViewer::updateNameLookupUrl() +void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp) { - LLViewerRegion* region = gAgent.getRegion(); - if (!region || !region->capabilitiesReceived()) + if (!regionp || !regionp->capabilitiesReceived()) { return; } @@ -5238,7 +5237,7 @@ void LLAppViewer::updateNameLookupUrl() bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL(); std::string name_lookup_url; name_lookup_url.reserve(128); // avoid a memory allocation below - name_lookup_url = region->getCapability("GetDisplayNames"); + name_lookup_url = regionp->getCapability("GetDisplayNames"); bool have_capability = !name_lookup_url.empty(); if (have_capability) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 6db45583eb..95e93be572 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -57,6 +57,7 @@ class LLImageDecodeThread; class LLTextureFetch; class LLWatchdogTimeout; class LLViewerJoystick; +class LLViewerRegion; extern LLTrace::BlockTimerStatHandle FTM_FRAME; @@ -209,7 +210,7 @@ public: // llcorehttp init/shutdown/config information. LLAppCoreHttp & getAppCoreHttp() { return mAppCoreHttp; } - void updateNameLookupUrl(); + void updateNameLookupUrl(const LLViewerRegion* regionp); protected: virtual bool initWindow(); // Initialize the viewer's window. diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index b6f120e644..431ca4fc05 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1029,7 +1029,7 @@ void LLEnvironment::onRegionChange() } if (!cur_region->capabilitiesReceived()) { - cur_region->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id) { LLEnvironment::instance().requestRegion(); }); + cur_region->setCapabilitiesReceivedCallback([](const LLUUID ®ion_id, LLViewerRegion* regionp) { LLEnvironment::instance().requestRegion(); }); return; } requestRegion(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2fde4fe49c..f007aefc70 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2241,7 +2241,7 @@ void LLViewerRegion::setSimulatorFeaturesReceived(bool received) mSimulatorFeaturesReceived = received; if (received) { - mSimulatorFeaturesReceivedSignal(getRegionID()); + mSimulatorFeaturesReceivedSignal(getRegionID(), this); mSimulatorFeaturesReceivedSignal.disconnect_all_slots(); } } @@ -3183,7 +3183,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received) // so that they can safely use getCapability(). if (received) { - mCapabilitiesReceivedSignal(getRegionID()); + mCapabilitiesReceivedSignal(getRegionID(), this); LLFloaterPermsDefault::sendInitialPerms(); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index dfd8c64f76..fcbf56c81f 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -94,7 +94,7 @@ public: NUM_PARTITIONS } eObjectPartitions; - typedef boost::signals2::signal caps_received_signal_t; + typedef boost::signals2::signal caps_received_signal_t; LLViewerRegion(const U64 &handle, const LLHost &host, diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp index 730aa3774f..d55e1b7cd3 100644 --- a/indra/newview/llwlhandlers.cpp +++ b/indra/newview/llwlhandlers.cpp @@ -51,7 +51,7 @@ bool LLEnvironmentRequest::initiate(LLEnvironment::environment_apply_fn cb) if (!cur_region->capabilitiesReceived()) { LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL; - cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID ®ion_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); + cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID ®ion_id, LLViewerRegion* regionp) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); }); return false; } -- cgit v1.3 From c9fc4349b7d4ab1f5a7bfc0125014a96a07e51a3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 11 May 2021 21:42:14 -0400 Subject: SL-10297: Move LL_ERRS crash location into the LL_ERRS macro itself. Introduce Oz's LLERROR_CRASH macro analogous to the old LLError::crashAndLoop() function. Change LL_ENDL macro so that, after calling flush(), if the CallSite is for LEVEL_ERROR, we invoke LLERROR_CRASH right there. Change the meaning of LLError::FatalFunction. It used to be responsible for the actual crash (hence crashAndLoop()). Now, instead, its role is to disrupt control flow in some other way if you DON'T want to crash: throw an exception, or call exit() or some such. Any FatalFunction that returns normally will fall into the new crash in LL_ENDL. Accordingly, the new default FatalFunction is a no-op lambda. This eliminates the need to test for empty (not set) FatalFunction in Log::flush(). Remove LLError::crashAndLoop() because the official LL_ERRS crash is now in LL_ENDL. One of the two common use cases for setFatalFunction() used to be to intercept control in the last moments before crashing -- not to crash or to avoid crashing, but to capture the LL_ERRS message in some way. Especially when that's temporary, though (e.g. LLLeap), saving and restoring the previous FatalFunction only works when the lifespans of the relevant objects are strictly LIFO. Either way, that's a misuse of FatalFunction. Fortunately the Recorder mechanism exactly addresses that case. Introduce a GenericRecorder template subclass, with LLError::addGenericRecorder(callable) that accepts a callable with suitable (level, message) signature, instantiates a GenericRecorder, adds it to the logging machinery and returns the RecorderPtr for possible later use with removeRecorder(). Change llappviewer.cpp's errorCallback() to an addGenericRecorder() callable. Its role was simply to update gDebugInfo["FatalMessage"] with the LL_ERRS message, then call writeDebugInfo(), before calling crashAndLoop() to finish crashing. Remove the crashAndLoop() call, retaining the gDebugInfo logic. Pass errorCallback() to LLError::addGenericRecorder() instead of setFatalFunction(). Oddly, errorCallback()'s crashAndLoop() call was conditional on a compile-time SHADER_CRASH_NONFATAL symbol. The new mechanism provides no way to support SHADER_CRASH_NONFATAL -- it is a Bad Idea to return normally from any LL_ERRS invocation! Rename LLLeapImpl::fatalFunction() to onError(). Instead of passing it to LLError::setFatalFunction(), pass it to addGenericRecorder(). Capture the returned RecorderPtr in mRecorder, replacing mPrevFatalFunction. Then ~LLLeapImpl() calls removeRecorder(mRecorder) instead of restoring mPrevFatalFunction (which, as noted above, was order-sensitive). Of course, every enabled Recorder is called with every log message. onError() and errorCallback() must specifically test for calls with LEVEL_ERROR. LLSingletonBase::logerrs() used to call LLError::getFatalFunction(), check the return and call it if non-empty, else call LLError::crashAndLoop(). Replace all that with LLERROR_CRASH. Remove from llappviewer.cpp the watchdog_llerrs_callback() and watchdog_killer_callback() functions. watchdog_killer_callback(), passed to Watchdog::init(), used to setFatalFunction(watchdog_llerrs_callback) and then invoke LL_ERRS() -- which seems a bit roundabout. watchdog_llerrs_callback(), in turn, replicated much of the logic in the primary errorCallback() function before replicating the crash from llwatchdog.cpp's default_killer_callback(). Instead, pass LLWatchdog::init() a lambda that invokes the LL_ERRS() message formerly found in watchdog_killer_callback(). It no longer needs to override FatalFunction with watchdog_llerrs_callback() because errorCallback() will still be called as a Recorder, obviating watchdog_llerrs_callback()'s first half; and LL_ENDL will handle the crash, obviating the second half. Remove from llappviewer.cpp the static fast_exit() function, which was simply an alias for _exit() acceptable to boost::bind(). Use a lambda directly calling _exit() instead of using boost::bind() at all. In the CaptureLog class in llcommon/tests/wrapllerrs.h, instead of statically referencing the wouldHaveCrashed() function from test.cpp, simply save and restore the current FatalFunction across the LLError::saveAndResetSettings() call. llerror_test.cpp calls setFatalFunction(fatalCall), where fatalCall() was a function that simply set a fatalWasCalled bool rather than actually crashing in any way. Of course, that implementation would now lead to crashing the test program. Make fatalCall() throw a new FatalWasCalled exception. Introduce a CATCH(LL_ERRS("tag"), "message") macro that expands to: LL_ERRS("tag") << "message" << LL_ENDL; within a try/catch block that catches FatalWasCalled and sets the same bool. Change all existing LL_ERRS() in llerror_test.cpp to corresponding CATCH() calls. In fact there's also an LL_DEBUGS(bad tag) invocation that exercises an LL_ERRS internal to llerror.cpp; wrap that too. --- indra/llcommon/llerror.cpp | 37 +++---------------- indra/llcommon/llerror.h | 22 +++++++++--- indra/llcommon/llerrorcontrol.h | 57 +++++++++++++++++++++++------ indra/llcommon/llleap.cpp | 48 ++++++++++++------------- indra/llcommon/llsingleton.cpp | 15 +------- indra/llcommon/tests/llerror_test.cpp | 58 +++++++++++++++++++----------- indra/llcommon/tests/wrapllerrs.h | 22 ++++++------ indra/newview/llappviewer.cpp | 67 +++++++++-------------------------- 8 files changed, 159 insertions(+), 167 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f876b8ee4a..9d775dcef3 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -549,7 +549,7 @@ namespace LLError mFileLevelMap(), mTagLevelMap(), mUniqueLogMessages(), - mCrashFunction(NULL), + mCrashFunction([](const std::string&){}), mTimeFunction(NULL), mRecorders(), mShouldLogCallCounter(0) @@ -728,7 +728,6 @@ namespace LLError::setDefaultLevel(LLError::LEVEL_INFO); LLError::setAlwaysFlush(true); LLError::setEnabledLogTypesMask(0xFFFFFFFF); - LLError::setFatalFunction(LLError::crashAndLoop); LLError::setTimeFunction(LLError::utcTime); // log_to_stderr is only false in the unit and integration tests to keep builds quieter @@ -1436,7 +1435,7 @@ namespace LLError if (site.mPrintOnce) { - std::ostringstream message_stream; + std::ostringstream message_stream; std::map::iterator messageIter = s->mUniqueLogMessages.find(message); if (messageIter != s->mUniqueLogMessages.end()) @@ -1457,8 +1456,8 @@ namespace LLError message_stream << "ONCE: "; s->mUniqueLogMessages[message] = 1; } - message_stream << message; - message = message_stream.str(); + message_stream << message; + message = message_stream.str(); } writeToRecorders(site, message); @@ -1466,10 +1465,7 @@ namespace LLError if (site.mLevel == LEVEL_ERROR) { g->mFatalMessage = message; - if (s->mCrashFunction) - { - s->mCrashFunction(message); - } + s->mCrashFunction(message); } } } @@ -1533,29 +1529,6 @@ namespace LLError return s->mShouldLogCallCounter; } -#if LL_WINDOWS - // VC80 was optimizing the error away. - #pragma optimize("", off) -#endif - void crashAndLoop(const std::string& message) - { - // Now, we go kaboom! - int* make_me_crash = NULL; - - *make_me_crash = 0; - - while(true) - { - // Loop forever, in case the crash didn't work? - } - - // this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever. - exit(EXIT_FAILURE); - } -#if LL_WINDOWS - #pragma optimize("", on) -#endif - std::string utcTime() { time_t now = time(NULL); diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index ffaa464d77..f8c0d03aea 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -382,11 +382,23 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_NEWLINE '\n' -#define LL_ENDL \ - LLError::End(); \ - LLError::Log::flush(_out, _site); \ - } \ - } while(0) +// Use this only in LL_ERRS or in a place that LL_ERRS may not be used +#define LLERROR_CRASH \ +{ \ + int* make_me_crash = NULL;\ + *make_me_crash = 0; \ + exit(*make_me_crash); \ +} + +#define LL_ENDL \ + LLError::End(); \ + LLError::Log::flush(_out, _site); \ + if (_site.mLevel == LLError::LEVEL_ERROR) \ + { \ + LLERROR_CRASH \ + } \ + } \ + } while(0) // NEW Macros for debugging, allow the passing of a string tag diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 25786d5457..e87bb7bf35 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -94,14 +94,16 @@ namespace LLError */ typedef boost::function FatalFunction; - LL_COMMON_API void crashAndLoop(const std::string& message); - // Default fatal function: access null pointer and loops forever LL_COMMON_API void setFatalFunction(const FatalFunction&); - // The fatal function will be called when an message of LEVEL_ERROR + // The fatal function will be called after an message of LEVEL_ERROR // is logged. Note: supressing a LEVEL_ERROR message from being logged // (by, for example, setting a class level to LEVEL_NONE), will keep - // the that message from causing the fatal funciton to be invoked. + // that message from causing the fatal function to be invoked. + // The passed FatalFunction will be the LAST log function called + // before LL_ERRS crashes its caller. A FatalFunction can throw an + // exception, or call exit(), to bypass the crash. It MUST disrupt the + // flow of control because no caller expects LL_ERRS to return. LL_COMMON_API FatalFunction getFatalFunction(); // Retrieve the previously-set FatalFunction @@ -147,14 +149,14 @@ namespace LLError virtual void recordMessage(LLError::ELevel, const std::string& message) = 0; // use the level for better display, not for filtering - virtual bool enabled() { return true; } + virtual bool enabled() { return true; } bool wantsTime(); bool wantsTags(); bool wantsLevel(); bool wantsLocation(); bool wantsFunctionName(); - bool wantsMultiline(); + bool wantsMultiline(); void showTime(bool show); void showTags(bool show); @@ -165,15 +167,35 @@ namespace LLError protected: bool mWantsTime; - bool mWantsTags; - bool mWantsLevel; - bool mWantsLocation; - bool mWantsFunctionName; - bool mWantsMultiline; + bool mWantsTags; + bool mWantsLevel; + bool mWantsLocation; + bool mWantsFunctionName; + bool mWantsMultiline; }; typedef boost::shared_ptr RecorderPtr; + /** + * Instantiate GenericRecorder with a callable(level, message) to get + * control on every log message without having to code an explicit + * Recorder subclass. + */ + template + class GenericRecorder: public Recorder + { + public: + GenericRecorder(const CALLABLE& callable): + mCallable(callable) + {} + void recordMessage(LLError::ELevel level, const std::string& message) override + { + mCallable(level, message); + } + private: + CALLABLE mCallable; + }; + /** * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership * while still ensuring that the allocated memory is eventually freed @@ -181,6 +203,19 @@ namespace LLError LL_COMMON_API void addRecorder(RecorderPtr); LL_COMMON_API void removeRecorder(RecorderPtr); // each error message is passed to each recorder via recordMessage() + /** + * Call addGenericRecorder() with a callable(level, message) to get + * control on every log message without having to code an explicit + * Recorder subclass. Save the returned RecorderPtr if you later want to + * call removeRecorder(). + */ + template + RecorderPtr addGenericRecorder(const CALLABLE& callable) + { + RecorderPtr ptr{ new GenericRecorder(callable) }; + addRecorder(ptr); + return ptr; + } LL_COMMON_API void logToFile(const std::string& filename); LL_COMMON_API void logToStderr(); diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index cf8f8cc6a5..e8ea0ab398 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -59,7 +59,6 @@ public: // pump name -- so it should NOT need tweaking for uniqueness. mReplyPump(LLUUID::generateNewID().asString()), mExpect(0), - mPrevFatalFunction(LLError::getFatalFunction()), // Instantiate a distinct LLLeapListener for this plugin. (Every // plugin will want its own collection of managed listeners, etc.) // Pass it a callback to our connect() method, so it can send events @@ -146,7 +145,9 @@ public: .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1)); // For our lifespan, intercept any LL_ERRS so we can notify plugin - LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1)); + mRecorder = LLError::addGenericRecorder( + [this](LLError::ELevel level, const std::string& message) + { onError(level, message); }); // Send child a preliminary event reporting our own reply-pump name -- // which would otherwise be pretty tricky to guess! @@ -162,8 +163,7 @@ public: virtual ~LLLeapImpl() { LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL; - // Restore original FatalFunction - LLError::setFatalFunction(mPrevFatalFunction); + LLError::removeRecorder(mRecorder); } // Listener for failed launch attempt @@ -377,28 +377,28 @@ public: return false; } - void fatalFunction(const std::string& error) + void onError(LLError::ELevel level, const std::string& error) { - // Notify plugin - LLSD event; - event["type"] = "error"; - event["error"] = error; - mReplyPump.post(event); - - // All the above really accomplished was to buffer the serialized - // event in our WritePipe. Have to pump mainloop a couple times to - // really write it out there... but time out in case we can't write. - LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - LLSD nop; - F64 until = (LLTimer::getElapsedSeconds() + 2).value(); - while (childin.size() && LLTimer::getElapsedSeconds() < until) + if (level == LLError::LEVEL_ERROR) { - mainloop.post(nop); + // Notify plugin + LLSD event; + event["type"] = "error"; + event["error"] = error; + mReplyPump.post(event); + + // All the above really accomplished was to buffer the serialized + // event in our WritePipe. Have to pump mainloop a couple times to + // really write it out there... but time out in case we can't write. + LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + LLSD nop; + F64 until = (LLTimer::getElapsedSeconds() + 2).value(); + while (childin.size() && LLTimer::getElapsedSeconds() < until) + { + mainloop.post(nop); + } } - - // forward the call to the previous FatalFunction - mPrevFatalFunction(error); } private: @@ -421,7 +421,7 @@ private: mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection; boost::scoped_ptr mBlocker; LLProcess::ReadPipe::size_type mExpect; - LLError::FatalFunction mPrevFatalFunction; + LLError::RecorderPtr mRecorder; boost::scoped_ptr mListener; }; diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index d0dcd463ff..4b1666563e 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -486,20 +486,7 @@ void LLSingletonBase::logerrs(std::initializer_list args) log(LLError::LEVEL_ERROR, args); // The other important side effect of LL_ERRS() is // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG) - std::ostringstream out; - for (auto arg : args) - { - out << arg; - } - auto crash = LLError::getFatalFunction(); - if (crash) - { - crash(out.str()); - } - else - { - LLError::crashAndLoop(out.str()); - } + LLERROR_CRASH; } std::string LLSingletonBase::demangle(const char* mangled) diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 8e1f4c14ac..148c18aabe 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -26,6 +26,7 @@ */ #include +#include #include "linden_common.h" @@ -69,21 +70,41 @@ namespace namespace { - static bool fatalWasCalled; - void fatalCall(const std::string&) { fatalWasCalled = true; } + static bool fatalWasCalled = false; + struct FatalWasCalled: public std::runtime_error + { + FatalWasCalled(const std::string& what): std::runtime_error(what) {} + }; + void fatalCall(const std::string& msg) { throw FatalWasCalled(msg); } } +// Because we use LLError::setFatalFunction(fatalCall), any LL_ERRS call we +// issue will throw FatalWasCalled. But we want the test program to continue. +// So instead of writing: +// LL_ERRS("tag") << "some message" << LL_ENDL; +// write: +// CATCH(LL_ERRS("tag"), "some message"); +#define CATCH(logcall, expr) \ + try \ + { \ + logcall << expr << LL_ENDL; \ + } \ + catch (const FatalWasCalled&) \ + { \ + fatalWasCalled = true; \ + } + namespace tut { class TestRecorder : public LLError::Recorder { public: TestRecorder() - { - showTime(false); - } + { + showTime(false); + } virtual ~TestRecorder() - {} + {} virtual void recordMessage(LLError::ELevel level, const std::string& message) @@ -252,7 +273,7 @@ namespace LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL; LL_INFOS("WriteTag") << "two" << LL_ENDL; LL_WARNS("WriteTag") << "three" << LL_ENDL; - LL_ERRS("WriteTag") << "four" << LL_ENDL; + CATCH(LL_ERRS("WriteTag"), "four"); } }; @@ -380,7 +401,7 @@ namespace std::string errorReturningLocation() { - LL_ERRS() << "die" << LL_ENDL; int this_line = __LINE__; + int this_line = __LINE__; CATCH(LL_ERRS(), "die"); return locationString(this_line); } } @@ -701,7 +722,7 @@ public: static void doDebug() { LL_DEBUGS() << "add dice" << LL_ENDL; } static void doInfo() { LL_INFOS() << "any idea" << LL_ENDL; } static void doWarn() { LL_WARNS() << "aim west" << LL_ENDL; } - static void doError() { LL_ERRS() << "ate eels" << LL_ENDL; } + static void doError() { CATCH(LL_ERRS(), "ate eels"); } static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } }; @@ -712,7 +733,7 @@ public: static void doDebug() { LL_DEBUGS() << "bed down" << LL_ENDL; } static void doInfo() { LL_INFOS() << "buy iron" << LL_ENDL; } static void doWarn() { LL_WARNS() << "bad word" << LL_ENDL; } - static void doError() { LL_ERRS() << "big easy" << LL_ENDL; } + static void doError() { CATCH(LL_ERRS(), "big easy"); } static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } }; @@ -874,13 +895,10 @@ namespace tut namespace { std::string writeTagWithSpaceReturningLocation() - { - LL_DEBUGS("Write Tag") << "not allowed" << LL_ENDL; int this_line = __LINE__; - - std::ostringstream location; - location << LLError::abbreviateFile(__FILE__).c_str() << "(" << this_line << ")"; - return location.str(); - } + { + int this_line = __LINE__; CATCH(LL_DEBUGS("Write Tag"), "not allowed"); + return locationString(this_line); + } }; namespace tut @@ -894,9 +912,9 @@ namespace tut std::string location = writeTagWithSpaceReturningLocation(); std::string expected = "Space is not allowed in a log tag at " + location; - ensure_message_field_equals(0, LEVEL_FIELD, "ERROR"); - ensure_message_field_equals(0, MSG_FIELD, expected); - ensure("fatal callback called", fatalWasCalled); + ensure_message_field_equals(0, LEVEL_FIELD, "ERROR"); + ensure_message_field_equals(0, MSG_FIELD, expected); + ensure("fatal callback called", fatalWasCalled); } } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index b07d5afbd8..3779fb41bc 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -44,10 +44,6 @@ #include #include -// statically reference the function in test.cpp... it's short, we could -// replicate, but better to reuse -extern void wouldHaveCrashed(const std::string& message); - struct WrapLLErrs { WrapLLErrs(): @@ -59,7 +55,8 @@ struct WrapLLErrs mPriorFatal(LLError::getFatalFunction()) { // Make LL_ERRS call our own operator() method - LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1)); + LLError::setFatalFunction( + [this](const std::string& message){ (*this)(message); }); } ~WrapLLErrs() @@ -199,11 +196,13 @@ public: // with that output. If it turns out that saveAndResetSettings() has // some bad effect, give up and just let the DEBUG level log messages // display. - : boost::noncopyable(), + : boost::noncopyable(), + mFatalFunction(LLError::getFatalFunction()), mOldSettings(LLError::saveAndResetSettings()), - mRecorder(new CaptureLogRecorder()) + mRecorder(new CaptureLogRecorder()) { - LLError::setFatalFunction(wouldHaveCrashed); + // reinstate the FatalFunction we just reset + LLError::setFatalFunction(mFatalFunction); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } @@ -219,17 +218,18 @@ public: /// for the sought string. std::string messageWith(const std::string& search, bool required=true) { - return boost::dynamic_pointer_cast(mRecorder)->messageWith(search, required); + return boost::dynamic_pointer_cast(mRecorder)->messageWith(search, required); } std::ostream& streamto(std::ostream& out) const { - return boost::dynamic_pointer_cast(mRecorder)->streamto(out); + return boost::dynamic_pointer_cast(mRecorder)->streamto(out); } private: + LLError::FatalFunction mFatalFunction; LLError::SettingsStoragePtr mOldSettings; - LLError::RecorderPtr mRecorder; + LLError::RecorderPtr mRecorder; }; #endif /* ! defined(LL_WRAPLLERRS_H) */ diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0b2cdff36c..b03e821d32 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -760,17 +760,6 @@ public: } }; -namespace { -// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide -// this little helper function. -void fast_exit(int rc) -{ - _exit(rc); -} - - -} - bool LLAppViewer::init() { @@ -822,9 +811,9 @@ bool LLAppViewer::init() if (rc >= 0) { // QAModeTermCode set, terminate with that rc on LL_ERRS. Use - // fast_exit() rather than exit() because normal cleanup depends too + // _exit() rather than exit() because normal cleanup depends too // much on successful startup! - LLError::setFatalFunction(boost::bind(fast_exit, rc)); + LLError::setFatalFunction([rc](const std::string&){ _exit(rc); }); } mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); @@ -2185,28 +2174,6 @@ bool LLAppViewer::cleanup() return true; } -// A callback for LL_ERRS() to call during the watchdog error. -void watchdog_llerrs_callback(const std::string &error_string) -{ - gLLErrorActivated = true; - - gDebugInfo["FatalMessage"] = error_string; - LLAppViewer::instance()->writeDebugInfo(); - -#ifdef LL_WINDOWS - RaiseException(0,0,0,0); -#else - raise(SIGQUIT); -#endif -} - -// A callback for the watchdog to call. -void watchdog_killer_callback() -{ - LLError::setFatalFunction(watchdog_llerrs_callback); - LL_ERRS() << "Watchdog killer event" << LL_ENDL; -} - bool LLAppViewer::initThreads() { static const bool enable_threads = true; @@ -2241,24 +2208,23 @@ bool LLAppViewer::initThreads() return true; } -void errorCallback(const std::string &error_string) +void errorCallback(LLError::ELevel level, const std::string &error_string) { + if (level == LLError::LEVEL_ERROR) + { #ifndef LL_RELEASE_FOR_DOWNLOAD - OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); + OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK); #endif - //Set the ErrorActivated global so we know to create a marker file - gLLErrorActivated = true; - - gDebugInfo["FatalMessage"] = error_string; - // We're not already crashing -- we simply *intend* to crash. Since we - // haven't actually trashed anything yet, we can afford to write the whole - // static info file. - LLAppViewer::instance()->writeDebugInfo(); + //Set the ErrorActivated global so we know to create a marker file + gLLErrorActivated = true; -#ifndef SHADER_CRASH_NONFATAL - LLError::crashAndLoop(error_string); -#endif + gDebugInfo["FatalMessage"] = error_string; + // We're not already crashing -- we simply *intend* to crash. Since we + // haven't actually trashed anything yet, we can afford to write the whole + // static info file. + LLAppViewer::instance()->writeDebugInfo(); + } } void LLAppViewer::initLoggingAndGetLastDuration() @@ -2269,7 +2235,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ); - LLError::setFatalFunction(errorCallback); + LLError::addGenericRecorder(&errorCallback); //LLError::setTimeFunction(getRuntime); // Remove the last ".old" log file. @@ -3030,7 +2996,8 @@ bool LLAppViewer::initWindow() if (use_watchdog) { - LLWatchdog::getInstance()->init(watchdog_killer_callback); + LLWatchdog::getInstance()->init( + [](){ LL_ERRS() << "Watchdog killer event" << LL_ENDL; }); } LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL; -- cgit v1.3 From 28862ab53b9e532bf6ff789743d80b33af10f395 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 12 May 2021 14:21:27 -0400 Subject: SL-10297: Clean up a few merge glitches. --- indra/newview/llappviewer.cpp | 29 ++++++++++++----------------- indra/test/test.cpp | 22 ++++++++-------------- 2 files changed, 20 insertions(+), 31 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c44690ac25..7d7d41fe22 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2298,10 +2298,6 @@ void LLAppViewer::initLoggingAndGetLastDuration() { LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; } - - // TBD - temporary location for fatal hook (should be above, but for now it logs...) - LL_DEBUGS("FatalHook") << "initial setting of default fatalhook" << LL_ENDL; - LLError::setFatalHook(fatalErrorHook); } bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, @@ -2998,16 +2994,15 @@ bool LLAppViewer::initWindow() use_watchdog = bool(watchdog_enabled_setting); } - LL_INFOS("AppInit") << "watchdog" - << (use_watchdog ? " " : " NOT ") - << "enabled" - << " (setting = " << watchdog_enabled_setting << ")" - << LL_ENDL; + LL_INFOS("AppInit") << "watchdog" + << (use_watchdog ? " " : " NOT ") + << "enabled" + << " (setting = " << watchdog_enabled_setting << ")" + << LL_ENDL; if (use_watchdog) { - LLWatchdog::getInstance()->init( - [](){ LL_ERRS() << "Watchdog killer event" << LL_ENDL; }); + LLWatchdog::getInstance()->init(); } LLNotificationsUI::LLNotificationManager::getInstance(); @@ -3441,8 +3436,8 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); - gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value()); - gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits()); + gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); + gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits()); gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple(); // The user is not logged on yet, but record the current grid choice login url @@ -3461,11 +3456,11 @@ void LLAppViewer::writeSystemInfo() // 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; + gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true); #else // LL_BUGSPLAT // "CrashNotHandled" is obsolete; it used (not very successsfully) // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze - gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false; + gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false); #endif // ! LL_BUGSPLAT // Insert crash host url (url to post crash log to) if configured. This insures @@ -3497,7 +3492,7 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); - gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); + gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin()); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); @@ -3627,7 +3622,7 @@ void LLAppViewer::handleViewerCrash() // 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; + gDebugInfo["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false); //Write out the crash status file //Use marker file style setup, as that's the simplest, especially since diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 571f502861..87c4a8d8a3 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -75,18 +75,7 @@ #include -LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message) -{ -#if LL_MSVC -#pragma warning (push) -#pragma warning (disable : 4702) // warning C4702: unreachable code -#endif - tut::fail("fatal error message: " + message); - return LLError::ERR_DO_NOT_CRASH; -#if LL_MSVC -#pragma warning (pop) -#endif -} +void wouldHaveCrashed(const std::string& message); namespace tut { @@ -157,7 +146,7 @@ public: mOldSettings(LLError::saveAndResetSettings()), mRecorder(new RecordToTempFile(pool)) { - LLError::setFatalHook(wouldHaveCrashed); + LLError::setFatalFunction(wouldHaveCrashed); LLError::setDefaultLevel(level); LLError::addRecorder(mRecorder); } @@ -523,6 +512,11 @@ void stream_groups(std::ostream& s, const char* app) } } +void wouldHaveCrashed(const std::string& message) +{ + tut::fail("llerrs message: " + message); +} + static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL; int main(int argc, char **argv) @@ -632,7 +626,7 @@ int main(int argc, char **argv) replayer.reset(new LLReplayLogReal(level, gAPRPoolp)); } } - LLError::setFatalHook(wouldHaveCrashed); + LLError::setFatalFunction(wouldHaveCrashed); std::string test_app_name(argv[0]); std::string test_log = test_app_name + ".log"; LLFile::remove(test_log); -- cgit v1.3