summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/CMakeLists.txt53
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake4
-rw-r--r--indra/cmake/LLAddBuildTest.cmake13
-rw-r--r--indra/cmake/Variables.cmake1
-rw-r--r--indra/cmake/bugsplat.cmake53
-rw-r--r--indra/linux_crash_logger/README.txt3
-rw-r--r--indra/llcommon/CMakeLists.txt9
-rw-r--r--indra/llcommon/llapp.cpp10
-rw-r--r--indra/llcommon/llerror.cpp75
-rw-r--r--indra/llcommon/llerror.h31
-rw-r--r--indra/llcommon/llerrorcontrol.h47
-rw-r--r--indra/llcommon/llleap.cpp31
-rw-r--r--indra/llcommon/llsingleton.cpp10
-rw-r--r--indra/llcommon/tests/llerror_test.cpp25
-rw-r--r--indra/llcommon/tests/wrapllerrs.h28
-rw-r--r--indra/llcorehttp/CMakeLists.txt1
-rw-r--r--indra/llcrashlogger/README.txt3
-rw-r--r--indra/llimage/CMakeLists.txt1
-rw-r--r--indra/llmath/CMakeLists.txt1
-rw-r--r--indra/mac_crash_logger/README.txt3
-rw-r--r--indra/newview/CMakeLists.txt66
-rw-r--r--indra/newview/llappdelegate-objc.mm10
-rw-r--r--indra/newview/llappviewer.cpp97
-rw-r--r--indra/newview/llappviewermacosx.cpp54
-rw-r--r--indra/newview/llappviewerwin32.cpp9
-rw-r--r--indra/newview/llviewerwindow.cpp3
-rw-r--r--indra/newview/llwatchdog.cpp24
-rw-r--r--indra/newview/llwatchdog.h6
-rwxr-xr-xindra/newview/viewer_manifest.py6
-rw-r--r--indra/test/CMakeLists.txt6
-rw-r--r--indra/test/test.cpp18
-rw-r--r--indra/win_crash_logger/README.txt3
32 files changed, 343 insertions, 361 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 53e5d7b6a5..db88e44127 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)
set(LEGACY_STDIO_LIBS)
@@ -50,7 +51,10 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
add_custom_target(viewer)
+if (NOT USE_BUGSPLAT)
add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
+endif (NOT USE_BUGSPLAT)
+
add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
add_subdirectory(${LIBS_OPEN_PREFIX}llui)
add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
@@ -64,29 +68,18 @@ add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
endif (ENABLE_MEDIA_PLUGINS)
if (LINUX)
- add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
if (INSTALL_PROPRIETARY)
include(LLAppearanceUtility)
add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR})
endif (INSTALL_PROPRIETARY)
- add_dependencies(viewer linux-crash-logger-strip-target)
-elseif (DARWIN)
- add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
- add_dependencies(viewer mac-crash-logger)
-elseif (WINDOWS)
- add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
- # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
- if (EXISTS ${VIEWER_DIR}win_setup)
- add_subdirectory(${VIEWER_DIR}win_setup)
- endif (EXISTS ${VIEWER_DIR}win_setup)
- # add_dependencies(viewer windows-setup windows-crash-logger)
- add_dependencies(viewer windows-crash-logger)
endif (LINUX)
-add_subdirectory(${VIEWER_PREFIX}newview)
-add_dependencies(viewer secondlife-bin)
-
-add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
+if (WINDOWS)
+ # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
+ if (EXISTS ${VIEWER_DIR}win_setup)
+ add_subdirectory(${VIEWER_DIR}win_setup)
+ endif (EXISTS ${VIEWER_DIR}win_setup)
+endif (WINDOWS)
# sets the 'startup project' for debugging from visual studio.
set_property(
@@ -94,6 +87,32 @@ 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")
+ if (LINUX)
+ add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
+ add_dependencies(viewer linux-crash-logger-strip-target)
+ elseif (DARWIN)
+ add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
+ add_dependencies(viewer mac-crash-logger)
+ elseif (WINDOWS)
+ add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
+ # add_dependencies(viewer windows-setup windows-crash-logger)
+ add_dependencies(viewer windows-crash-logger)
+ endif (LINUX)
+endif (USE_BUGSPLAT)
+
+add_subdirectory(${VIEWER_PREFIX}newview)
+add_dependencies(viewer secondlife-bin)
+
+add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
+
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 429bda473b..ec27267d9d 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -65,7 +65,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)
@@ -75,7 +75,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 (FMODSTUDIO)
set(debug_files ${debug_files} fmodL.dll)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 4932e9044f..4937c2a9d7 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})
@@ -224,6 +230,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..5f5cc51f63 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 REQUIRED
+ NO_DEFAULT_PATH 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/linux_crash_logger/README.txt b/indra/linux_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/linux_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index eeb315ead6..79aa18eaec 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -4,6 +4,7 @@ project(llcommon)
include(00-Common)
include(LLCommon)
+include(bugsplat)
include(Linking)
include(Boost)
include(LLSharedLibs)
@@ -258,10 +259,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/llapp.cpp b/indra/llcommon/llapp.cpp
index 3dab632aef..252d08c830 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -528,7 +528,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()
@@ -808,7 +813,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);
@@ -845,7 +852,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);
@@ -898,6 +907,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/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 411412c883..922c003443 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"
@@ -499,7 +500,7 @@ namespace LLError
LevelMap mTagLevelMap;
std::map<std::string, unsigned int> mUniqueLogMessages;
- LLError::FatalFunction mCrashFunction;
+ LLError::FatalHook mFatalHook;
LLError::TimeFunction mTimeFunction;
Recorders mRecorders;
@@ -536,7 +537,7 @@ namespace LLError
mFileLevelMap(),
mTagLevelMap(),
mUniqueLogMessages(),
- mCrashFunction(NULL),
+ mFatalHook(NULL),
mTimeFunction(NULL),
mRecorders(),
mShouldLogCallCounter(0)
@@ -708,9 +709,9 @@ namespace
LLError::Settings::getInstance()->reset();
LLError::setDefaultLevel(LLError::LEVEL_INFO);
- LLError::setAlwaysFlush(true);
- LLError::setEnabledLogTypesMask(0xFFFFFFFF);
- LLError::setFatalFunction(LLError::crashAndLoop);
+
+ LLError::setAlwaysFlush(true);
+ LLError::setEnabledLogTypesMask(0xFFFFFFFF);
LLError::setTimeFunction(LLError::utcTime);
// log_to_stderr is only false in the unit and integration tests to keep builds quieter
@@ -745,16 +746,20 @@ namespace LLError
commonInit(user_dir, app_dir, log_to_stderr);
}
- void setFatalFunction(const FatalFunction& f)
+ void setFatalHook(const FatalHook& fatal_hook)
{
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- s->mCrashFunction = f;
- }
-
- FatalFunction getFatalFunction()
+ LL_DEBUGS("FatalHook") << "set fatal hook to " << (fatal_hook ? "non-null" : "null")
+ << " was " << (s->mFatalHook ? "non-null" : "null")
+ << LL_ENDL;
+ s->mFatalHook = fatal_hook;
+ }
+
+ FatalHook getFatalHook()
{
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- return s->mCrashFunction;
+ LL_DEBUGS("FatalHook") << "read fatal hook was " << (s->mFatalHook ? "non-null" : "null") << LL_ENDL;
+ return s->mFatalHook;
}
std::string getFatalMessage()
@@ -1410,12 +1415,12 @@ namespace LLError
return ;
}
- void Log::flush(std::ostringstream* out, const CallSite& site)
+ ErrFatalHookResult Log::flush(std::ostringstream* out, const CallSite& site)
{
LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
if (!lock.isLocked())
{
- return;
+ 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,
@@ -1423,7 +1428,7 @@ namespace LLError
// DO NOT resurrect them.
if (Settings::wasDeleted() || Globals::wasDeleted())
{
- return;
+ return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
}
Globals* g = Globals::getInstance();
@@ -1457,7 +1462,7 @@ namespace LLError
}
else
{
- return;
+ return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
}
}
else
@@ -1473,12 +1478,19 @@ namespace LLError
if (site.mLevel == LEVEL_ERROR)
{
- g->mFatalMessage = message;
- if (s->mCrashFunction)
- {
- s->mCrashFunction(message);
- }
+ if (s->mFatalHook)
+ {
+ return s->mFatalHook(message);
+ }
+ else
+ {
+ return ERR_CRASH; // calling macro should crash
+ }
}
+ else
+ {
+ return ERR_DO_NOT_CRASH; // not ERROR, so do not crash
+ }
}
}
@@ -1541,29 +1553,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..18d11cfa9d 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -193,14 +193,20 @@ namespace LLError
*/
struct CallSite;
+
+ enum ErrFatalHookResult { ERR_DO_NOT_CRASH, ERR_CRASH };
class LL_COMMON_API Log
{
public:
static bool shouldLog(CallSite&);
static std::ostringstream* out();
+
static void flush(std::ostringstream* out, char* message);
- static void flush(std::ostringstream*, const CallSite&);
+
+ // returns false iff the calling macro should crash
+ static ErrFatalHookResult flush(std::ostringstream*, const CallSite&);
+
static std::string demangle(const char* mangled);
/// classname<TYPE>()
template <typename T>
@@ -271,6 +277,7 @@ namespace LLError
class LL_COMMON_API NoClassInfo { };
// used to indicate no class info known for logging
+
//LLCallStacks keeps track of call stacks and output the call stacks to log file
//when LLAppViewer::handleViewerCrash() is triggered.
//
@@ -382,10 +389,24 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_NEWLINE '\n'
-#define LL_ENDL \
- LLError::End(); \
- LLError::Log::flush(_out, _site); \
- } \
+#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 \
+{ \
+ *gCauseCrash = 0; \
+ exit(*gCauseCrash); \
+}
+
+#define LL_ENDL \
+ LLError::End(); \
+ if (LLError::ERR_CRASH == LLError::Log::flush(_out, _site)) \
+ 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 bfa2269025..d001a3bd03 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -93,40 +93,27 @@ namespace LLError
Control functions.
*/
- typedef boost::function<void(const std::string&)> 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
+ // 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<LLError::ErrFatalHookResult(const std::string&)> 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.
+ // (by, for example, setting a class level to LEVEL_NONE), will also
+ // prevent the fatal_hook being called and the resulting deliberate crash
- LL_COMMON_API FatalFunction getFatalFunction();
- // Retrieve the previously-set FatalFunction
+ /// Retrieve the previously-set FatalHook
+ LL_COMMON_API FatalHook getFatalHook();
LL_COMMON_API std::string getFatalMessage();
- // Retrieve the message last passed to FatalFunction, if any
-
- /// temporarily override the FatalFunction for the duration of a
- /// particular scope, e.g. for unit tests
- class LL_COMMON_API OverrideFatalFunction
- {
- public:
- OverrideFatalFunction(const FatalFunction& func):
- mPrev(getFatalFunction())
- {
- setFatalFunction(func);
- }
- ~OverrideFatalFunction()
- {
- setFatalFunction(mPrev);
- }
-
- private:
- FatalFunction mPrev;
- };
+ // Retrieve the message last passed to LL_ERRS, if any
typedef std::string (*TimeFunction)();
LL_COMMON_API std::string utcTime();
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index cf8f8cc6a5..8293c35516 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
@@ -145,9 +144,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::setFatalFunction(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(),
@@ -162,8 +158,6 @@ public:
virtual ~LLLeapImpl()
{
LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
- // Restore original FatalFunction
- LLError::setFatalFunction(mPrevFatalFunction);
}
// Listener for failed launch attempt
@@ -377,30 +371,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);
- }
-
- // forward the call to the previous FatalFunction
- mPrevFatalFunction(error);
- }
-
private:
/// We always want to listen on mReplyPump with wstdin(); under some
/// circumstances we'll also echo other LLEventPumps to the plugin.
@@ -421,7 +391,6 @@ private:
mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
LLProcess::ReadPipe::size_type mExpect;
- LLError::FatalFunction mPrevFatalFunction;
boost::scoped_ptr<LLLeapListener> mListener;
};
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index d3d25201b2..f410bd6a92 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -512,15 +512,7 @@ void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, co
// https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
std::ostringstream out;
out << p1 << p2 << p3 << p4;
- 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..cdc2bf8c87 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::ErrFatalHookResult fatalHook(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::setFatalFunction(fatalCall);
+ LLError::setFatalHook(fatalHook);
LLError::addRecorder(mRecorder);
}
@@ -777,30 +781,33 @@ namespace tut
// proper cached, efficient lookup of filtering
void ErrorTestObject::test<15>()
{
- LLError::setDefaultLevel(LLError::LEVEL_NONE);
+ LLError::setDefaultLevel(LLError::LEVEL_NONE);
+
+ // Note that the setFatalHook in the ErrorTestData constructor
+ // increments the shouldLogCallCount
TestAlpha::doInfo();
ensure_message_count(0);
- ensure_equals("first check", LLError::shouldLogCallCount(), 1);
+ ensure_equals("first check", LLError::shouldLogCallCount(), 2);
TestAlpha::doInfo();
ensure_message_count(0);
- ensure_equals("second check", LLError::shouldLogCallCount(), 1);
+ ensure_equals("second check", LLError::shouldLogCallCount(), 2);
LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
TestAlpha::doInfo();
ensure_message_count(1);
- ensure_equals("third check", LLError::shouldLogCallCount(), 2);
+ ensure_equals("third check", LLError::shouldLogCallCount(), 3);
TestAlpha::doInfo();
ensure_message_count(2);
- ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
+ ensure_equals("fourth check", LLError::shouldLogCallCount(), 3);
LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
TestAlpha::doInfo();
ensure_message_count(2);
- ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
+ ensure_equals("fifth check", LLError::shouldLogCallCount(), 4);
TestAlpha::doInfo();
ensure_message_count(2);
- ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
+ ensure_equals("sixth check", LLError::shouldLogCallCount(), 4);
}
template<> template<>
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index b07d5afbd8..a6c44d5fdd 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -46,25 +46,24 @@
// 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::ErrFatalHookResult 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()),
- // Save shutdown function called by LL_ERRS
- mPriorFatal(LLError::getFatalFunction())
+ :mPriorErrorSettings(LLError::saveAndResetSettings())
+ ,mPriorFatalHook(LLError::getFatalHook())
{
// Make LL_ERRS call our own operator() method
- LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1));
+ LLError::setFatalHook(boost::bind(&WrapLLErrs::operator(), this, _1));
}
~WrapLLErrs()
{
- LLError::setFatalFunction(mPriorFatal);
+ LLError::setFatalHook(mPriorFatalHook);
LLError::restoreSettings(mPriorErrorSettings);
}
@@ -73,7 +72,7 @@ struct WrapLLErrs
FatalException(const std::string& what): LLException(what) {}
};
- void 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;
@@ -109,7 +108,7 @@ struct WrapLLErrs
std::string error;
LLError::SettingsStoragePtr mPriorErrorSettings;
- LLError::FatalFunction mPriorFatal;
+ LLError::FatalHook mPriorFatalHook;
};
/**
@@ -199,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::setFatalFunction(wouldHaveCrashed);
+ LLError::setFatalHook(wouldHaveCrashed);
LLError::setDefaultLevel(level);
LLError::addRecorder(mRecorder);
}
@@ -212,6 +212,7 @@ public:
{
LLError::removeRecorder(mRecorder);
LLError::restoreSettings(mOldSettings);
+ LLError::setFatalHook(mPriorFatalHook);
}
/// Don't assume the message we want is necessarily the LAST log message
@@ -229,6 +230,7 @@ public:
private:
LLError::SettingsStoragePtr mOldSettings;
+ LLError::FatalHook mPriorFatalHook;
LLError::RecorderPtr mRecorder;
};
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 11b2e3e929..8efaf75582 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/llcrashlogger/README.txt b/indra/llcrashlogger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/llcrashlogger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
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 999bee0a3f..552e820127 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/mac_crash_logger/README.txt b/indra/mac_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/mac_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 88667bdc11..a4cbe73e8a 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)
@@ -96,18 +94,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
@@ -1406,11 +1404,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
@@ -1738,10 +1736,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)
+ PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
+endif (USE_BUGSPLAT)
# add package files
file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
@@ -1818,9 +1816,12 @@ if (WINDOWS)
media_plugin_libvlc
media_plugin_example
winmm_shim
- windows-crash-logger
)
+ if (NOT USE_BUGSPLAT)
+ LIST(APPEND COPY_INPUT_DEPENDENCIES windows-crash-logger)
+ endif (NOT USE_BUGSPLAT)
+
if (ADDRESS_SIZE EQUAL 64)
list(APPEND COPY_INPUT_DEPENDENCIES
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk_x64.dll
@@ -1875,10 +1876,11 @@ if (WINDOWS)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
- add_dependencies(${VIEWER_BINARY_NAME}
- SLPlugin
- windows-crash-logger
- )
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin)
+
+ if (NOT USE_BUGSPLAT)
+ add_dependencies(${VIEWER_BINARY_NAME} windows-crash-logger)
+ endif (NOT USE_BUGSPLAT)
# sets the 'working directory' for debugging from visual studio.
# Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
@@ -2029,11 +2031,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.")
@@ -2044,13 +2046,16 @@ if (LINUX)
# These are the generated targets that are copied to package/
set(COPY_INPUT_DEPENDENCIES
${VIEWER_BINARY_NAME}
- linux-crash-logger
SLPlugin
media_plugin_gstreamer010
media_plugin_libvlc
llcommon
)
+ if (NOT USE_BUGSPLAT)
+ LIST(APPEND COPY_INPUT_DEPENDENCIES linux-crash-logger)
+ endif (NOT USE_BUGSPLAT)
+
add_custom_command(
OUTPUT ${product}.tar.bz2
COMMAND ${PYTHON_EXECUTABLE}
@@ -2178,8 +2183,11 @@ if (DARWIN)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
)
- add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef mac-crash-logger)
- add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef)
+
+ if (NOT USE_BUGSPLAT)
+ add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
+ endif (NOT USE_BUGSPLAT)
if (ENABLE_SIGNING)
set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}")
@@ -2221,7 +2229,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)
@@ -2238,7 +2246,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
- set(VIEWER_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger")
+ set(VIEWER_EXE_GLOBS "'${product}' SLPlugin")
set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger")
set(VIEWER_LIB_GLOB "*.dylib")
endif (DARWIN)
@@ -2276,7 +2284,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
@@ -2360,9 +2368,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/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 47fde299c7..ccab9173a9 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;
@@ -299,9 +301,13 @@ struct AttachmentInfo
// We "happen to know" that info[0].basename is "SecondLife.old" -- due to
// the fact that BugsplatMac only notices a crash during the viewer run
- // following the crash. Replace .old with .log to reduce confusion.
+ // following the crash.
+ // The Bugsplat service doesn't respect the MIME type above when returning
+ // the log data to a browser, so take this opportunity to rename the file
+ // from <base>.old to <base>_log.txt
info[0].basename =
- boost::filesystem::path(info[0].pathname).stem().string() + ".log";
+ boost::filesystem::path(info[0].pathname).stem().string() + "_log.txt";
+ infos("attachmentsForBugsplatStartupManager attaching log " + info[0].basename);
NSMutableArray *attachments = [[NSMutableArray alloc] init];
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 75574df00e..581e69ec40 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -723,14 +723,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);
@@ -755,17 +755,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()
{
@@ -809,18 +799,8 @@ 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));
- }
+ // 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"));
@@ -2142,28 +2122,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;
@@ -2198,7 +2156,7 @@ bool LLAppViewer::initThreads()
return true;
}
-void errorCallback(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);
@@ -2213,8 +2171,10 @@ void errorCallback(const std::string &error_string)
// static info file.
LLAppViewer::instance()->writeDebugInfo();
-#ifndef SHADER_CRASH_NONFATAL
- LLError::crashAndLoop(error_string);
+#ifdef SHADER_CRASH_NONFATAL
+ return LLError::ERR_DO_NOT_CRASH;
+#else
+ return LLError::ERR_CRASH;
#endif
}
@@ -2226,8 +2186,8 @@ void LLAppViewer::initLoggingAndGetLastDuration()
LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
);
- LLError::setFatalFunction(errorCallback);
- //LLError::setTimeFunction(getRuntime);
+
+ // TBD fatal hook belongs here
// Remove the last ".old" log file.
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
@@ -2289,6 +2249,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...)
+ LL_DEBUGS("FatalHook") << "initial setting of default fatalhook" << LL_ENDL;
+ LLError::setFatalHook(fatalErrorHook);
}
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
@@ -2985,11 +2949,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();
@@ -3435,12 +3404,18 @@ 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 - the intent here to to avoid calling it a freeze
+ gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
+#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
@@ -3668,6 +3643,8 @@ void LLAppViewer::handleViewerCrash()
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
+ gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
+
// Close the debug file
pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead.
}
@@ -3766,9 +3743,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;
- gLastExecEvent = LAST_EXEC_FROZE;
-
+ LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
+ gLastExecEvent = LAST_EXEC_OTHER_CRASH;
}
else
{
@@ -5535,11 +5511,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/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 3111540a13..784a104573 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -68,39 +68,21 @@ namespace
int gArgC;
char** gArgV;
LLAppViewerMacOSX* gViewerAppPtr = NULL;
-
- void (*gOldTerminateHandler)() = NULL;
std::string gHandleSLURL;
}
-static void exceptionTerminateHandler()
-{
- // reinstall default terminate() handler in case we re-terminate.
- if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);
- // treat this like a regular viewer crash, with nice stacktrace etc.
- long *null_ptr;
- null_ptr = 0;
- *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
- //LLAppViewer::handleViewerCrash();
- // we've probably been killed-off before now, but...
- gOldTerminateHandler(); // call old terminate() handler
-}
-
void constructViewer()
{
// Set the working dir to <bundle>/Contents/Resources
if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)
{
- LL_WARNS() << "Could not change directory to "
+ LL_WARNS("InitOSX") << "Could not change directory to "
<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
<< LL_ENDL;
}
gViewerAppPtr = new LLAppViewerMacOSX();
- // install unexpected exception handler
- gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
-
gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
}
@@ -109,7 +91,7 @@ bool initViewer()
bool ok = gViewerAppPtr->init();
if(!ok)
{
- LL_WARNS() << "Application init failed." << LL_ENDL;
+ LL_WARNS("InitOSX") << "Application init failed." << LL_ENDL;
}
else if (!gHandleSLURL.empty())
{
@@ -172,7 +154,7 @@ class CrashMetadataSingleton: public CrashMetadata, public LLSingleton<CrashMeta
std::string get_metadata(const LLSD& info, const LLSD::String& key) const
{
std::string data(info[key].asString());
- LL_INFOS() << " " << key << "='" << data << "'" << LL_ENDL;
+ LL_INFOS("Bugsplat") << " " << key << "='" << data << "'" << LL_ENDL;
return data;
}
};
@@ -188,17 +170,17 @@ CrashMetadataSingleton::CrashMetadataSingleton()
LLSD info;
if (! static_file.is_open())
{
- LL_INFOS() << "Can't open '" << staticDebugPathname
+ LL_WARNS("Bugsplat") << "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("Bugsplat") << "Can't parse '" << staticDebugPathname
<< "'; no metadata about previous run" << LL_ENDL;
}
else
{
- LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL;
+ LL_INFOS("Bugsplat") << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL;
logFilePathname = get_metadata(info, "SLLog");
userSettingsPathname = get_metadata(info, "SettingsFilename");
OSInfo = get_metadata(info, "OSInfo");
@@ -218,7 +200,7 @@ CrashMetadata& CrashMetadata_instance()
void infos(const std::string& message)
{
- LL_INFOS() << message << LL_ENDL;
+ LL_INFOS("InitOSX", "Bugsplat") << message << LL_ENDL;
}
int main( int argc, char **argv )
@@ -241,14 +223,11 @@ bool LLAppViewerMacOSX::init()
{
bool success = LLAppViewer::init();
-#if LL_SEND_CRASH_REPORTS
if (success)
{
LLAppViewer* pApp = LLAppViewer::instance();
pApp->initCrashReporting();
}
-#endif
-
return success;
}
@@ -333,11 +312,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)
@@ -368,6 +348,10 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
{
+#if defined LL_BUGSPLAT
+ LL_DEBUGS("InitOSX", "Bugsplat") << "using BugSplat crash logger" << LL_ENDL;
+#elif LL_SEND_CRASH_REPORTS
+ LL_DEBUGS("InitOSX") << "Initializing legacy crash logger" << LL_ENDL;
std::string command_str = "mac-crash-logger.app";
std::stringstream pid_str;
@@ -379,6 +363,9 @@ void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
LL_WARNS() << "about to launch mac-crash-logger" << pid_str.str()
<< " " << logdir << " " << appname << LL_ENDL;
launchApplication(&command_str, &args);
+#else
+ LL_DEBUGS("InitOSX") << "No crash logger enabled" << LL_ENDL;
+#endif // ! LL_BUGSPLAT
}
std::string LLAppViewerMacOSX::generateSerialNumber()
@@ -390,7 +377,8 @@ std::string LLAppViewerMacOSX::generateSerialNumber()
CFStringRef serialNumber = NULL;
io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
IOServiceMatching("IOPlatformExpertDevice"));
- if (platformExpert) {
+ if (platformExpert)
+ {
serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
CFSTR(kIOPlatformSerialNumberKey),
kCFAllocatorDefault, 0);
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 156a1c5893..9f8b1745d4 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -174,7 +174,7 @@ static void exceptionTerminateHandler()
long *null_ptr;
null_ptr = 0;
*null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
- //LLAppViewer::handleViewerCrash();
+
// we've probably been killed-off before now, but...
gOldTerminateHandler(); // call old terminate() handler
}
@@ -362,10 +362,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
-#if LL_SEND_CRASH_REPORTS
- // ::SetUnhandledExceptionFilter(catchallCrashHandler);
-#endif
-
// Set a debug info flag to indicate if multiple instances are running.
bool found_other_instance = !create_app_mutex();
gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance);
@@ -810,8 +806,7 @@ bool LLAppViewerWin32::beingDebugged()
bool LLAppViewerWin32::restoreErrorTrap()
{
- return true;
- //return LLWinDebug::checkExceptionHandler();
+ return true; // we don't check for handler collisions on windows, so just say they're ok
}
void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0cc1e0df06..556f16e0b4 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1812,7 +1812,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;
diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp
index 6273f10c69..0aa0280b25 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/newview/llwatchdog.cpp
@@ -31,15 +31,6 @@
const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000;
-void default_killer_callback()
-{
-#ifdef LL_WINDOWS
- RaiseException(0,0,0,0);
-#else
- raise(SIGQUIT);
-#endif
-}
-
// This class runs the watchdog timing thread.
class LLWatchdogTimerThread : public LLThread
{
@@ -158,11 +149,10 @@ void LLWatchdogTimeout::ping(const std::string& state)
}
// LLWatchdog
-LLWatchdog::LLWatchdog() :
- mSuspectsAccessMutex(),
- mTimer(NULL),
- mLastClockCount(0),
- mKillerCallback(&default_killer_callback)
+LLWatchdog::LLWatchdog()
+ :mSuspectsAccessMutex()
+ ,mTimer(NULL)
+ ,mLastClockCount(0)
{
}
@@ -184,9 +174,8 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
unlockThread();
}
-void LLWatchdog::init(killer_event_callback func)
+void LLWatchdog::init()
{
- mKillerCallback = func;
if(!mSuspectsAccessMutex && !mTimer)
{
mSuspectsAccessMutex = new LLMutex();
@@ -253,8 +242,7 @@ void LLWatchdog::run()
mTimer->stop();
}
- LL_INFOS() << "Watchdog detected error:" << LL_ENDL;
- mKillerCallback();
+ LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL;
}
}
diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h
index 9a6624258e..ce5cf748f4 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/newview/llwatchdog.h
@@ -83,9 +83,7 @@ public:
void add(LLWatchdogEntry* e);
void remove(LLWatchdogEntry* e);
- typedef boost::function<void (void)> killer_event_callback;
-
- void init(killer_event_callback func = NULL);
+ void init();
void run();
void cleanup();
@@ -98,8 +96,6 @@ private:
LLMutex* mSuspectsAccessMutex;
LLWatchdogTimerThread* mTimer;
U64 mLastClockCount;
-
- killer_event_callback mKillerCallback;
};
#endif // LL_LLTHREADWATCHDOG_H
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index f5edde1923..2105b419e7 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1057,10 +1057,8 @@ class DarwinManifest(ViewerManifest):
# our apps
executable_path = {}
- for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
- # plugin launcher
- (os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
- ):
+ embedded_apps = [ (os.path.join("llplugin", "slplugin"), "SLPlugin.app") ]
+ for app_bld_dir, app in embedded_apps:
self.path2basename(os.path.join(os.pardir,
app_bld_dir, self.args['configuration']),
app)
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 87536e146b..251100867f 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(
@@ -83,6 +83,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
${LEGACY_STDIO_LIBS}
${LLDATABASE_LIBRARIES}
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 87c4a8d8a3..b16fcb84d6 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -58,8 +58,7 @@
#include <gtest/gtest.h>
#endif
-#if LL_MSVC
-#pragma warning (push)
+#if LL_WINDOWS
#pragma warning (disable : 4702) // warning C4702: unreachable code
#endif
#include <boost/iostreams/tee.hpp>
@@ -75,7 +74,11 @@
#include <fstream>
-void wouldHaveCrashed(const std::string& message);
+LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message)
+{
+ tut::fail("fatal error message: " + message);
+ return LLError::ERR_DO_NOT_CRASH;
+}
namespace tut
{
@@ -146,7 +149,7 @@ public:
mOldSettings(LLError::saveAndResetSettings()),
mRecorder(new RecordToTempFile(pool))
{
- LLError::setFatalFunction(wouldHaveCrashed);
+ LLError::setFatalHook(wouldHaveCrashed);
LLError::setDefaultLevel(level);
LLError::addRecorder(mRecorder);
}
@@ -512,11 +515,6 @@ 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)
@@ -626,7 +624,7 @@ int main(int argc, char **argv)
replayer.reset(new LLReplayLogReal(level, gAPRPoolp));
}
}
- LLError::setFatalFunction(wouldHaveCrashed);
+ LLError::setFatalHook(wouldHaveCrashed);
std::string test_app_name(argv[0]);
std::string test_log = test_app_name + ".log";
LLFile::remove(test_log);
diff --git a/indra/win_crash_logger/README.txt b/indra/win_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/win_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.