Port Crashpad support from alchemy, with some small tweaks

Moved initCrashReporting into LLAppViewer, everything we use there is
crossplatform enough that duplicating code is silly

Removes unused gCrashSettings
Adds MBFatalError, that's right, Crash Loop is now translatable!
Adds consent notification prompt to first login... enjoy that, everyone.
This commit is contained in:
Liru Færs
2019-10-20 11:43:25 -04:00
parent 8a2407ecbb
commit 432bf03f0a
32 changed files with 821 additions and 1569 deletions

View File

@@ -389,6 +389,54 @@
<key>version</key>
<string>2.3</string>
</map>
<key>crashpad</key>
<map>
<key>canonical_repo</key>
<string>https://git.alchemyviewer.org/alchemy/thirdparty/3p-crashpad</string>
<key>copyright</key>
<string>Copyright 2014 The Crashpad Authors. All rights reserved.</string>
<key>description</key>
<string>Crashpad is a crash-reporting system.</string>
<key>license</key>
<string>Apache 2.0</string>
<key>license_file</key>
<string>LICENSES/crashpad.txt</string>
<key>name</key>
<string>crashpad</string>
<key>platforms</key>
<map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>849f515d4d77162c15614ebff8599c13</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows/crashpad-365c520b.6-windows-6.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>7ea820b6a2cfa172f47d673c07dfa62c</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://pkg.alchemyviewer.org/repository/autobuild-external/crashpad/windows64/crashpad-365c520b.6-windows64-6.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>365c520b.6</string>
</map>
<key>curl</key>
<map>
<key>copyright</key>
@@ -1237,104 +1285,6 @@
<key>version</key>
<string>1.0pre3.190390340</string>
</map>
<key>google_breakpad</key>
<map>
<key>copyright</key>
<string>Copyright (c) 2006, Google Inc.</string>
<key>description</key>
<string>Breakpad is a crossplatform library for capturing crash callstacks and runtime data.</string>
<key>license</key>
<string>bsd</string>
<key>license_file</key>
<string>LICENSES/google_breakpad.txt</string>
<key>name</key>
<string>google_breakpad</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>9f963eb1728e6d5077d4feba805d4896</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/google_breakpad-9e60a27-darwin-201511222009.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>2d43c6a149cd9c89ba19e884579b1e25</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1836/4096/google_breakpad-1413.501824-darwin64-501824.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>52257e5eb166a0b69c9c0c38f6e1920e</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-google-breakpad/rev/273079/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130329.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>3709a51d4d5dff5ec0c4656623eaa05d</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://depot.alchemyviewer.org/pub/linux64/lib-trusty/google_breakpad-9e60a27-linux64-201603240004.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>fa7f683ba4ddd7db777c78c8213d2e46</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://depot.alchemyviewer.org/pub/windows/lib-vc141/google_breakpad-7398ce15b79da-windows-201703090621.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>71ffc5cae4da7e2e7aac856da44cb8c4</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://depot.alchemyviewer.org/pub/windows64/lib-vc141/google_breakpad-7398ce15b79da-windows64-201703081616.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>9e60a27</string>
</map>
<key>gperftools</key>
<map>
<key>copyright</key>

View File

@@ -17,19 +17,6 @@ set(CMAKE_C_FLAGS_RELEASE
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
"-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
# Configure crash reporting
set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
set(NON_RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in developer builds")
if(RELEASE_CRASH_REPORTING)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DLL_SEND_CRASH_REPORTS=1")
endif()
if(NON_RELEASE_CRASH_REPORTING)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_SEND_CRASH_REPORTS=1")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1")
endif()
# Don't bother with a MinSizeRel build.
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING
"Supported build types." FORCE)
@@ -55,6 +42,14 @@ if (WINDOWS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
endif (WORD_SIZE EQUAL 32)
if (FULL_DEBUG_SYMS OR USE_CRASHPAD)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FULL")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL")
else ()
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FASTLINK")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FASTLINK")
endif ()
if (USE_LTO)
if(INCREMENTAL_LINK)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LTCG:INCREMENTAL")
@@ -306,6 +301,13 @@ endif (LINUX OR DARWIN)
if (STANDALONE)
add_definitions(-DLL_STANDALONE=1)
else (STANDALONE)
#Enforce compile-time correctness for fmt strings
add_definitions(-DFMT_STRING_ALIAS=1)
if(USE_CRASHPAD)
add_definitions(-DUSE_CRASHPAD=1 -DCRASHPAD_URL="${CRASHPAD_URL}")
endif()
set(${ARCH}_linux_INCLUDES
atk-1.0
cairo

View File

@@ -22,6 +22,7 @@ set(cmake_SOURCE_FILES
ConfigurePkgConfig.cmake
CURL.cmake
Copy3rdPartyLibs.cmake
CrashPad.cmake
Cwdebug.cmake
DBusGlib.cmake
DeploySharedLibs.cmake
@@ -32,7 +33,6 @@ set(cmake_SOURCE_FILES
FindCARes.cmake
FindColladadom.cmake
FindGLOD.cmake
FindGoogleBreakpad.cmake
FindGooglePerfTools.cmake
FindHunSpell.cmake
FindNDOF.cmake
@@ -47,7 +47,6 @@ set(cmake_SOURCE_FILES
GStreamer010Plugin.cmake
Glui.cmake
Glut.cmake
GoogleBreakpad.cmake
GooglePerfTools.cmake
Hunspell.cmake
JPEG.cmake

View File

@@ -0,0 +1,22 @@
# -*- cmake -*-
include(Prebuilt)
include(Variables)
if(USE_CRASHPAD)
if (USESYSTEMLIBS)
else (USESYSTEMLIBS)
use_prebuilt_binary(crashpad)
if (WINDOWS)
set(CRASHPAD_LIBRARIES
debug client.lib util.lib base.lib
optimized client.lib util.lib base.lib)
elseif (LINUX)
else (DARWIN)
endif ()
set(CRASHPAD_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/crashpad)
endif (USESYSTEMLIBS)
endif()

View File

@@ -1,40 +0,0 @@
# -*- cmake -*-
# - Find Google BreakPad
# Find the Google BreakPad includes and library
# This module defines
# BREAKPAD_INCLUDE_DIRECTORIES, where to find the Goole BreakPad includes.
# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad.
# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad.
# also defined, but not for general use are
# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library.
FIND_PATH(BREAKPAD_INCLUDE_DIRECTORIES common/using_std_string.h PATH_SUFFIXES google_breakpad)
SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client)
FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY
NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES}
)
IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES)
SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY})
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES")
ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES)
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO")
ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_INCLUDE_DIRECTORIES)
IF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}")
ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND)
IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Google BreakPad library")
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
MARK_AS_ADVANCED(
BREAKPAD_EXCEPTION_HANDLER_LIBRARY
BREAKPAD_INCLUDE_DIRECTORIES
)

View File

@@ -1,26 +0,0 @@
# -*- cmake -*-
include(Prebuilt)
if (STANDALONE)
set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON)
include(FindGoogleBreakpad)
else (STANDALONE)
use_prebuilt_binary(google_breakpad)
if (DARWIN)
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler)
endif (DARWIN)
if (LINUX)
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client)
endif (LINUX)
if (WINDOWS)
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common)
endif (WINDOWS)
# yes, this does look dumb, no, it's not incorrect
# I think it's incorrect: the second one should go --Aleric
set(BREAKPAD_INCLUDE_DIRECTORIES
${LIBS_PREBUILT_DIR}/include/google_breakpad
${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad
${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad
${LIBS_PREBUILT_LEGACY_DIR}/include/google_breakpad/google_breakpad
)
endif (STANDALONE)

View File

@@ -36,6 +36,11 @@ option(USE_PRECOMPILED_HEADERS "Enable use of precompiled header directives wher
option(USE_LTO "Enable Whole Program Optimization and related folding and binary reduction routines" OFF)
option(UNATTENDED "Disable use of uneeded tooling for automated builds" OFF)
# Configure crash reporting
option(USE_CRASHPAD "Build support for crashpad reporting engine" OFF)
set(CRASHPAD_URL "" CACHE STRING "Crashpad endpoint url")
set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files")
# Media Plugins
option(ENABLE_MEDIA_PLUGINS "Turn off building media plugins if they are imported by third-party library mechanism" ON)
option(LIBVLCPLUGIN "Turn off building support for libvlc plugin" ON)

View File

@@ -13,7 +13,6 @@ include(Boost)
include(OpenSSL)
include(LLSharedLibs)
include(Json)
include(GoogleBreakpad)
include(Copy3rdPartyLibs)
include(ZLIB)
include(URIPARSER)
@@ -291,7 +290,6 @@ target_link_libraries(
llcommon
PUBLIC
absl::hash
${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}
${APRUTIL_LIBRARIES}
${APR_LIBRARIES}
${EXPAT_LIBRARIES}

View File

@@ -368,13 +368,6 @@ const U32 MAP_ITEM_CLASSIFIED = 0x08;
const U32 MAP_ITEM_ADULT_EVENT = 0x09;
const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
// Crash reporter behavior
const char* const CRASH_SETTINGS_FILE = "settings_crash_behavior.xml";
const char* const CRASH_BEHAVIOR_SETTING = "CrashSubmitBehavior";
const S32 CRASH_BEHAVIOR_ASK = 0;
const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1;
const S32 CRASH_BEHAVIOR_NEVER_SEND = 2;
// Export/Import return values
const S32 EXPORT_SUCCESS = 0;
const S32 EXPORT_ERROR_PERMISSIONS = -1;

View File

@@ -25,9 +25,8 @@
*/
#include "linden_common.h"
#include "llapp.h"
#include <cstdlib>
#include "llapp.h"
#ifdef LL_DARWIN
#include <sys/types.h>
@@ -45,7 +44,6 @@
#include "llstl.h" // for DeletePointer()
#include "llstring.h"
#include "lleventtimer.h"
#include "exception_handler.h"
//
// Signal handling
@@ -57,12 +55,6 @@
LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);
BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
bool windows_post_minidump_callback(const wchar_t* dump_path,
const wchar_t* minidump_id,
void* context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion,
bool succeeded);
#else
# include <signal.h>
# include <unistd.h> // for fork()
@@ -70,18 +62,6 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
void setup_signals();
void default_unix_signal_handler(int signum, siginfo_t *info, void *);
#if LL_LINUX
#include "client/linux/handler/minidump_descriptor.h"
static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc,
void* context,
bool succeeded);
#else
// Called by breakpad exception handler after the minidump has been generated.
bool unix_post_minidump_callback(const char *dump_dir,
const char *minidump_id,
void *context, bool succeeded);
#endif
# if LL_DARWIN
/* OSX doesn't support SIGRT* */
S32 LL_SMACKDOWN_SIGNAL = SIGUSR1;
@@ -98,7 +78,7 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2;
#endif // LL_WINDOWS
// the static application instance
LLApp* LLApp::sApplication = NULL;
LLApp* LLApp::sApplication = nullptr;
// Allows the generation of core files for post mortem under gdb
// and disables crashlogger
@@ -110,7 +90,7 @@ BOOL LLApp::sLogInSignal = FALSE;
// static
LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status
LLAppErrorHandler LLApp::sErrorHandler = NULL;
LLAppErrorHandler LLApp::sErrorHandler = nullptr;
BOOL LLApp::sErrorThreadRunning = FALSE;
#if !LL_WINDOWS
LLApp::child_map LLApp::sChildMap;
@@ -119,13 +99,12 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
#endif
LLApp::LLApp() : mThreadErrorp(NULL)
LLApp::LLApp()
: mThreadErrorp(nullptr)
{
commonCtor();
}
static void* sCrashLoggerReserve = NULL;
void LLApp::commonCtor()
{
// Set our status to running
@@ -150,34 +129,11 @@ void LLApp::commonCtor()
// Set the application to this instance.
sApplication = this;
mExceptionHandler = 0;
#if LL_WINDOWS
sCrashLoggerReserve = VirtualAlloc(NULL, 512*1024, MEM_COMMIT|MEM_RESERVE, PAGE_NOACCESS);
#else
sCrashLoggerReserve = malloc(512*1024);
#endif
// initialize the buffer to write the minidump filename to
// (this is used to avoid allocating memory in the crash handler)
memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH);
mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
}
#if LL_WINDOWS
static bool clear_CrashLoggerReserve_callback(void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion)
{
VirtualFree(sCrashLoggerReserve, 0, MEM_RELEASE);
return true;
}
#else
static bool clear_CrashLoggerReserve_callback(void* context)
{
free(sCrashLoggerReserve);
return true;
}
#endif
LLApp::LLApp(LLErrorThread *error_thread) :
mThreadErrorp(error_thread)
{
@@ -198,11 +154,9 @@ LLApp::~LLApp()
if (mThreadErrorp)
{
delete mThreadErrorp;
mThreadErrorp = NULL;
mThreadErrorp = nullptr;
}
if(mExceptionHandler != 0) delete mExceptionHandler;
LLCommon::cleanupClass();
}
@@ -216,8 +170,8 @@ LLApp* LLApp::instance()
LLSD LLApp::getOption(const std::string& name) const
{
LLSD rv;
LLSD::array_const_iterator iter = mOptions.beginArray();
LLSD::array_const_iterator end = mOptions.endArray();
auto iter = mOptions.beginArray();
auto end = mOptions.endArray();
for(; iter != end; ++iter)
{
rv = (*iter)[name];
@@ -264,9 +218,9 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
#if LL_WINDOWS
//Windows changed command line parsing. Deal with it.
S32 slen = value.length() - 1;
S32 start = 0;
S32 end = slen;
size_t slen = value.length() - 1;
size_t start = 0;
size_t end = slen;
if (argv[ii][start]=='"')start++;
if (argv[ii][end]=='"')end--;
if (start!=0 || end!=slen)
@@ -343,92 +297,17 @@ void LLApp::setupErrorHandling()
// Error handling is done by starting up an error handling thread, which just sleeps and
// occasionally checks to see if the app is in an error state, and sees if it needs to be run.
#if LL_WINDOWS
#if LL_SEND_CRASH_REPORTS
EnableCrashingOnCrashes();
// This sets a callback to handle w32 signals to the console window.
// The viewer shouldn't be affected, sicne its a windowed app.
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
// Install the Google Breakpad crash handler for Windows
if(mExceptionHandler == 0)
{
mExceptionHandler = new google_breakpad::ExceptionHandler(
std::wstring(mDumpPath.begin(),mDumpPath.end()), //Dump path
clear_CrashLoggerReserve_callback,
windows_post_minidump_callback,
0,
google_breakpad::ExceptionHandler::HANDLER_ALL);
if (mExceptionHandler)
{
mExceptionHandler->set_handle_debug_exceptions(true);
}
}
#endif
#else
#if !LL_WINDOWS
//
// Start up signal handling.
//
// There are two different classes of signals. Synchronous signals are delivered to a specific
// thread, asynchronous signals can be delivered to any thread (in theory)
//
setup_signals();
// Add google breakpad exception handler configured for Darwin/Linux.
bool installHandler = true;
#if LL_DARWIN
// For the special case of Darwin, we do not want to install the handler if
// the process is being debugged as the app will exit with value ABRT (6) if
// we do. Unfortunately, the code below which performs that test relies on
// the structure kinfo_proc which has been tagged by apple as an unstable
// API. We disable this test for shipping versions to avoid conflicts with
// future releases of Darwin. This test is really only needed for developers
// starting the app from a debugger anyway.
#ifndef LL_RELEASE_FOR_DOWNLOAD
int mib[4];
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
struct kinfo_proc info;
memset(&info, 0, sizeof(info));
size_t size = sizeof(info);
int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
if((result == 0) || (errno == ENOMEM))
{
// P_TRACED flag is set, so this process is being debugged; do not install
// the handler
if(info.kp_proc.p_flag & P_TRACED) installHandler = false;
}
else
{
// Failed to discover if the process is being debugged; default to
// installing the handler.
installHandler = true;
}
if(installHandler && (mExceptionHandler == 0))
{
mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, clear_CrashLoggerReserve_callback, &unix_post_minidump_callback, 0, true, 0);
}
#endif
#elif LL_LINUX
if(installHandler && (mExceptionHandler == 0))
{
if (mDumpPath.empty())
{
mDumpPath = "/tmp";
}
google_breakpad::MinidumpDescriptor desc(mDumpPath);
mExceptionHandler = new google_breakpad::ExceptionHandler(desc, clear_CrashLoggerReserve_callback, unix_minidump_callback, NULL, true, -1);
}
#endif
#endif // ! LL_WINDOWS
#if !defined(USE_CRASHPAD)
startErrorThread();
#endif
}
@@ -466,7 +345,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler)
LLApp::sErrorHandler = handler;
}
// static
void LLApp::runErrorHandler()
{
@@ -479,7 +357,6 @@ void LLApp::runErrorHandler()
LLApp::setStopped();
}
// static
void LLApp::setStatus(EAppStatus status)
{
@@ -494,43 +371,12 @@ void LLApp::setError()
setStatus(APP_STATUS_ERROR);
}
void LLApp::setMiniDumpDir(const std::string &path)
{
if (path.empty())
{
mDumpPath = "/tmp";
}
else
{
mDumpPath = path;
}
if(mExceptionHandler == 0) return;
#ifdef LL_WINDOWS
wchar_t buffer[MAX_MINDUMP_PATH_LENGTH];
mbstowcs(buffer, mDumpPath.c_str(), MAX_MINDUMP_PATH_LENGTH);
mExceptionHandler->set_dump_path(std::wstring(buffer));
#elif LL_LINUX
//google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
mExceptionHandler->set_minidump_descriptor(desc);
#else
mExceptionHandler->set_dump_path(mDumpPath);
#endif
}
void LLApp::setDebugFileNames(const std::string &path)
{
mStaticDebugFileName = path + "static_debug_info.log";
mDynamicDebugFileName = path + "dynamic_debug_info.log";
}
void LLApp::writeMiniDump()
{
if(mExceptionHandler == 0) return;
mExceptionHandler->WriteMinidump();
}
// static
void LLApp::setQuitting()
{
@@ -585,13 +431,6 @@ bool LLApp::isExiting()
void LLApp::disableCrashlogger()
{
// Disable Breakpad exception handler.
if (mExceptionHandler != 0)
{
delete mExceptionHandler;
mExceptionHandler = 0;
}
sDisableCrashlogger = TRUE;
}
@@ -660,12 +499,6 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *except
ms_sleep(10);
}
//
// Generate a minidump if we can.
//
// TODO: This needs to be ported over form the viewer-specific
// LLWinDebug class
//
// At this point, we always want to exit the app. There's no graceful
// recovery for an unhandled exception.
@@ -965,150 +798,4 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
}
}
}
#if LL_LINUX
bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded)
{
// Copy minidump file path into fixed buffer in the app instance to avoid
// heap allocations in a crash handler.
// path format: <dump_dir>/<minidump_id>.dmp
//HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space
//to avoid doing allocation during crash.
char * path = LLApp::instance()->getMiniDumpFilename();
int dir_path_len = strlen(path);
// The path must not be truncated.
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len;
llassert( (remaining - strlen(minidump_desc.path())) > 5);
path += dir_path_len;
if (dir_path_len > 0 && path[-1] != '/')
{
*path++ = '/';
--remaining;
}
strncpy(path, minidump_desc.path(), remaining);
LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
LLApp::runErrorHandler();
#ifndef LL_RELEASE_FOR_DOWNLOAD
clear_signals();
return false;
#else
return true;
#endif
}
#endif
bool unix_post_minidump_callback(const char *dump_dir,
const char *minidump_id,
void *context, bool succeeded)
{
// Copy minidump file path into fixed buffer in the app instance to avoid
// heap allocations in a crash handler.
// path format: <dump_dir>/<minidump_id>.dmp
int dirPathLength = strlen(dump_dir);
int idLength = strlen(minidump_id);
// The path must not be truncated.
llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
char * path = LLApp::instance()->getMiniDumpFilename();
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
strncpy(path, dump_dir, remaining);
remaining -= dirPathLength;
path += dirPathLength;
if (remaining > 0 && dirPathLength > 0 && path[-1] != '/')
{
*path++ = '/';
--remaining;
}
if (remaining > 0)
{
strncpy(path, minidump_id, remaining);
remaining -= idLength;
path += idLength;
strncpy(path, ".dmp", remaining);
}
LL_INFOS() << "generated minidump: " << path << LL_ENDL;
LLApp::runErrorHandler();
#ifndef LL_RELEASE_FOR_DOWNLOAD
clear_signals();
return false;
#else
return true;
#endif
}
#endif // !WINDOWS
#ifdef LL_WINDOWS
bool windows_post_minidump_callback(const wchar_t* dump_path,
const wchar_t* minidump_id,
void* context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion,
bool succeeded)
{
char * path = LLApp::instance()->getMiniDumpFilename();
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
size_t bytesUsed;
bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining));
remaining -= bytesUsed;
path += bytesUsed;
if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\')
{
*path++ = '\\';
--remaining;
}
if(remaining > 0)
{
bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining));
remaining -= bytesUsed;
path += bytesUsed;
}
if(remaining > 0)
{
strncpy(path, ".dmp", remaining);
}
LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
// *TODO: Translate the signals/exceptions into cross-platform stuff
// Windows implementation
LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL;
if (LLApp::isError())
{
LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
}
// Flag status to error, so thread_error starts its work
LLApp::setError();
// Block in the exception handler until the app has stopped
// This is pretty sketchy, but appears to work just fine
while (!LLApp::isStopped())
{
ms_sleep(10);
}
#ifndef LL_RELEASE_FOR_DOWNLOAD
return false;
#else
return true;
#endif
}
#endif

View File

@@ -60,10 +60,6 @@ public:
};
#endif
namespace google_breakpad {
class ExceptionHandler; // See exception_handler.h
}
class LL_COMMON_API LLApp : public LLOptionInterface
{
friend class LLErrorThread;
@@ -233,22 +229,11 @@ public:
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
//@}
// the maximum length of the minidump filename returned by getMiniDumpFilename()
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
// change the directory where Breakpad minidump files are written to
void setMiniDumpDir(const std::string &path);
void setDebugFileNames(const std::string &path);
// Return the Google Breakpad minidump filename after a crash.
char *getMiniDumpFilename() { return mMinidumpPath; }
std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
// Write out a Google Breakpad minidump file.
void writeMiniDump();
#if !LL_WINDOWS
//
// Child process handling (Unix only for now)
@@ -281,8 +266,6 @@ protected:
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
std::string mDumpPath; //output path for google breakpad. Dependency workaround.
#if !LL_WINDOWS
static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
typedef std::map<pid_t, LLChildInfo> child_map; // Map key is a PID
@@ -290,16 +273,13 @@ protected:
static LLAppChildCallback sDefaultChildCallback;
#endif
void startErrorThread();
/**
* @brief This method is called at the end, just prior to deinitializing curl.
*/
void stopErrorThread();
private:
// Contains the filename of the minidump file after a crash.
char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
void startErrorThread();
std::string mStaticDebugFileName;
std::string mDynamicDebugFileName;
@@ -323,11 +303,8 @@ private:
std::vector<LLLiveFile*> mLiveFiles;
//@}
private:
// the static application instance if it was created.
static LLApp* sApplication;
google_breakpad::ExceptionHandler * mExceptionHandler;
#if !LL_WINDOWS
friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);

View File

@@ -960,5 +960,4 @@ P(webProfileResponders);
P(wholeModelFeeResponder);
P(wholeModelUploadResponder);
P2(XMLRPCResponder, connect_40s);
P2(crashLoggerResponder, transfer_300s);
P(getUpdateInfoResponder);

View File

@@ -12,6 +12,7 @@ include(BuildPackagesInfo)
include(BuildVersion)
include(BuildBranding)
include(CMakeCopyIfDifferent)
include(CrashPad)
include(DBusGlib)
include(FMODSTUDIO)
include(GeneratePrecompiledHeader)
@@ -49,6 +50,11 @@ include(WinManifest)
include(ZLIB)
include(URIPARSER)
if(USE_CRASHPAD)
include_directories(${CRASHPAD_INCLUDE_DIRS})
endif(USE_CRASHPAD)
include_directories(
${STATEMACHINE_INCLUDE_DIRS}
${DBUSGLIB_INCLUDE_DIRS}
@@ -143,7 +149,6 @@ set(viewer_SOURCE_FILES
llconfirmationmanager.cpp
llconsole.cpp
llcontrolavatar.cpp
llcrashlogger.cpp
llcurrencyuimanager.cpp
llcylinder.cpp
lldaycyclemanager.cpp
@@ -681,7 +686,6 @@ set(viewer_HEADER_FILES
llconfirmationmanager.h
llconsole.h
llcontrolavatar.h
llcrashlogger.h
llcurrencyuimanager.h
llcylinder.h
lldaycyclemanager.h
@@ -1375,7 +1379,6 @@ set(viewer_APPSETTINGS_FILES
app_settings/settings.xml
app_settings/settings_ascent.xml
app_settings/settings_ascent_coa.xml
app_settings/settings_crash_behavior.xml
app_settings/settings_files.xml
app_settings/settings_per_account.xml
app_settings/settings_sh.xml
@@ -1624,6 +1627,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${PNG_PRELOAD_ARCHIVES}
${ZLIB_PRELOAD_ARCHIVES}
${GOOGLE_PERFTOOLS_LIBRARIES}
${CRASHPAD_LIBRARIES}
${LLAUDIO_LIBRARIES}
${LLAUDIO_VORBIS_LIBRARIES}
${LLCHARACTER_LIBRARIES}
@@ -1823,8 +1827,10 @@ if (INSTALL)
include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)
endif (INSTALL)
if (PACKAGE)
if (PACKAGE AND USE_CRASHPAD)
# Breakpad symbol-file generation
set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${VIEWER_CHANNEL_NOSPACE}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}-symbols)
set(SYMBOL_SEARCH_DIRS "")
if (WINDOWS)
list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
@@ -1854,7 +1860,6 @@ if (PACKAGE)
set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest)
endif (LINUX)
if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
if(GEN_IS_MULTI_CONFIG)
set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE})
else()
@@ -1875,14 +1880,14 @@ if (PACKAGE)
DEPENDS generate_breakpad_symbols.py
VERBATIM)
add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}")
add_dependencies(generate_breakpad_symbols ${VIEWER_BINARY_NAME})
if(VIEWER_COPY_MANIFEST)
add_dependencies(generate_breakpad_symbols ${VIEWER_COPY_MANIFEST})
endif(VIEWER_COPY_MANIFEST)
add_dependencies(llpackage generate_breakpad_symbols)
endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING)
endif (PACKAGE)
add_custom_target(generate_symbols DEPENDS "${VIEWER_SYMBOL_FILE}" ${VIEWER_BINARY_NAME} "${VIEWER_COPY_MANIFEST}")
add_dependencies(generate_symbols ${VIEWER_BINARY_NAME})
if (WINDOWS OR LINUX)
add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}")
endif (WINDOWS OR LINUX)
add_dependencies(llpackage generate_symbols)
endif ()
# Add tests
if (LL_TESTS)

View File

@@ -2538,17 +2538,6 @@ This should be as low as possible, but too low may break functionality</string>
<integer>1</integer>
</map>
<!-- Standard SL options (To my knowledge) -->
<key>CrashHostUrl</key>
<map>
<key>Comment</key>
<string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://crash.singularityviewer.org/report.php</string>>
</map>
<key>AFKTimeout</key>
<map>
<key>Comment</key>
@@ -18971,24 +18960,13 @@ This should be as low as possible, but too low may break functionality</string>
<key>CrashSubmitBehavior</key>
<map>
<key>Comment</key>
<string>Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report)</string>
<string>Controls behavior when viewer crashes (0 = never send crash report, 1 = always send crash report)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>CrashReportID</key>
<map>
<key>Comment</key>
<string>ID of the last crash report sent. Zero indicates that no crash report has been sent. Non-zero value can be useful infermation for developers to track a specific issue</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
<integer>-1</integer>
</map>
<key>EveryoneCopy</key>

View File

@@ -1,15 +0,0 @@
<llsd>
<map>
<key>CrashSubmitBehavior</key>
<map>
<key>Comment</key>
<string>Controls behavior when viewer crashes (0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report)</string>
<key>Persist</key>
<integer>2</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
</map>
</map>
</llsd>

View File

@@ -43,13 +43,6 @@
<key>Requirement</key>
<integer>1</integer>
</map>
<key>CrashSettings</key>
<map>
<key>Name</key>
<string>settings_crash_behavior.xml</string>
<key>Requirement</key>
<integer>1</integer>
</map>
</map>
</map>
<key>User</key>
@@ -65,11 +58,6 @@
<key>NameFromSetting</key>
<string>ClientSettingsFile</string>
</map>
<key>CrashSettings</key>
<map>
<key>Name</key>
<string>settings_crash_behavior.xml</string>
</map>
</map>
</map>
<key>Account</key>

File diff suppressed because it is too large Load Diff

View File

@@ -76,6 +76,7 @@ public:
bool quitRequested() { return mQuitRequested; }
bool logoutRequestSent() { return mLogoutRequestSent; }
bool isSecondInstance() { return mSecondInstance; }
void writeDebugInfo(bool isStatic=true);
@@ -86,7 +87,7 @@ public:
virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.
// return false if the error trap needed restoration.
virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report?
void initCrashReporting(); // What to do with crash report?
static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon.
// Thread accessors
@@ -113,7 +114,7 @@ public:
void loadNameCache();
void saveNameCache();
void removeMarkerFile(bool leave_logout_marker = false);
void removeMarkerFiles();
void removeDumpDir();
// LLAppViewer testing helpers.
@@ -125,14 +126,13 @@ public:
virtual void forceErrorSoftwareException();
virtual void forceErrorDriverCrash();
// *NOTE: There are currently 3 settings files:
// "Global", "PerAccount" and "CrashSettings"
// *NOTE: There are currently 2 settings files:
// "Global", and "PerAccount"
// The list is found in app_settings/settings_files.xml
// but since they are used explicitly in code,
// the follow consts should also do the trick.
static const std::string sGlobalSettingsName;
static const std::string sPerAccountSettingsName;
static const std::string sCrashSettingsName;
// Load settings from the location specified by loction_key.
// Key availale and rules for loading, are specified in
@@ -158,6 +158,7 @@ public:
void handleLoginComplete();
LLAllocator & getAllocator() { return mAlloc; }
// On LoginCompleted callback
typedef boost::signals2::signal<void (void)> login_completed_signal_t;
login_completed_signal_t mOnLoginCompleted;
@@ -172,7 +173,8 @@ public:
static void metricsSend(bool enable_reporting);
protected:
virtual bool initWindow(); // Initialize the viewer's window.
virtual bool initLogging(); // Initialize log files, logging system, return false on failure.
virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system
void initLoggingInternal();
virtual void initConsole() {}; // Initialize OS level debugging console.
virtual bool initHardwareTest() { return true; } // A false result indicates the app should quit.
virtual bool initSLURLHandler();
@@ -189,7 +191,6 @@ private:
void initMaxHeapSize();
bool initThreads(); // Initialize viewer threads, return false on failure.
bool initConfiguration(); // Initialize settings from the command line/config file.
bool initCache(); // Initialize local client cache.
void checkMemory() ;
@@ -202,8 +203,9 @@ private:
void writeSystemInfo(); // Write system info to "debug_info.log"
bool anotherInstanceRunning();
void initMarkerFile();
void processMarkerFiles();
static void recordMarkerVersion(LLAPRFile& marker_file);
bool markerIsSameVersion(const std::string& marker_name) const;
void idle();
void idleShutdown();
@@ -226,8 +228,7 @@ private:
LLAPRFile mMarkerFile; // A file created to indicate the app is running.
std::string mLogoutMarkerFileName;
apr_file_t* mLogoutMarkerFile; // A file created to indicate the app is running.
LLAPRFile mLogoutMarkerFile; // A file created to indicate the app is running.
LLOSInfo mSysOSInfo;
bool mReportedCrash;

View File

@@ -119,7 +119,6 @@ int main( int argc, char **argv )
}
delete viewer_app_ptr;
viewer_app_ptr = NULL;
return 0;
}
@@ -143,20 +142,12 @@ bool LLAppViewerLinux::init()
bool success = LLAppViewer::init();
#if LL_SEND_CRASH_REPORTS
if (success)
{
LLAppViewer* pApp = LLAppViewer::instance();
pApp->initCrashReporting();
}
#endif
return success;
}
bool LLAppViewerLinux::restoreErrorTrap()
{
// *NOTE:Mani there is a case for implementing this or the mac.
// *NOTE:Mani there is a case for implementing this on the mac.
// Linux doesn't need it to my knowledge.
return true;
}
@@ -347,12 +338,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
}
#endif // LL_DBUS_ENABLED
void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
{
// Singu Note: this is where original code forks crash logger process.
// Singularity doesn't need it
}
bool LLAppViewerLinux::beingDebugged()
{
static enum {unknown, no, yes} debugged = unknown;
@@ -397,7 +382,7 @@ bool LLAppViewerLinux::beingDebugged()
#endif
}
bool LLAppViewerLinux::initLogging()
void LLAppViewerLinux::initLoggingAndGetLastDuration()
{
// Remove the last stack trace, if any
// This file is no longer created, since the move to Google Breakpad
@@ -406,7 +391,7 @@ bool LLAppViewerLinux::initLogging()
gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
LLFile::remove(old_stack_file);
return LLAppViewer::initLogging();
LLAppViewer::initLoggingAndGetLastDuration();
}
bool LLAppViewerLinux::initParseCommandLine(LLCommandLineParser& clp)

View File

@@ -66,7 +66,7 @@ protected:
virtual bool restoreErrorTrap();
virtual void initCrashReporting(bool reportFreeze);
virtual bool initLogging();
virtual void initLoggingAndGetLastDuration();
virtual bool initParseCommandLine(LLCommandLineParser& clp);
virtual bool initSLURLHandler();

View File

@@ -260,12 +260,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
return reset_count == 0;
}
void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
{
// Singu Note: this is where original code forks crash logger process.
// Singularity doesn't need it
}
std::string LLAppViewerMacOSX::generateSerialNumber()
{
char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore

View File

@@ -32,12 +32,6 @@
#include "llviewerprecompiledheaders.h"
#if defined(_DEBUG)
# if _MSC_VER >= 1400 // Visual C++ 2005 or later
# define WINDOWS_CRT_MEM_CHECKS 1
# endif
#endif
#include "llwindowwin32.h" // *FIX: for setting gIconResource.
#include "llappviewerwin32.h"
@@ -73,19 +67,6 @@
#include "llcommandlineparser.h"
#include "lltrans.h"
// *FIX:Mani - This hack is to fix a linker issue with libndofdev.lib
// The lib was compiled under VS2005 - in VS2003 we need to remap assert
#ifdef LL_DEBUG
#ifdef LL_MSVC7
extern "C" {
void _wassert(const wchar_t * _Message, const wchar_t *_File, unsigned _Line)
{
LL_ERRS() << _Message << LL_ENDL;
}
}
#endif
#endif
const std::string LLAppViewerWin32::sWindowClass = "Second Life";
// Create app mutex creates a unique global windows object.
@@ -101,7 +82,7 @@ bool create_app_mutex()
bool result = true;
LPCWSTR unique_mutex_name = L"SecondLifeAppMutex";
HANDLE hMutex;
hMutex = CreateMutex(NULL, TRUE, unique_mutex_name);
hMutex = CreateMutex(nullptr, TRUE, unique_mutex_name);
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
result = false;
@@ -240,7 +221,9 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine);
#if !defined(USE_CRASHPAD)
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
#endif
// Set a debug info flag to indicate if multiple instances are running.
bool found_other_instance = !create_app_mutex();
@@ -332,7 +315,7 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
delete viewer_app_ptr;
viewer_app_ptr = NULL;
viewer_app_ptr = nullptr;
//start updater
if(LLAppViewer::sUpdaterInfo)
@@ -392,13 +375,13 @@ void LLAppViewerWin32::disableWinErrorReporting()
const S32 MAX_CONSOLE_LINES = 500;
void create_console()
static bool create_console()
{
CONSOLE_SCREEN_BUFFER_INFO coninfo;
// allocate a console for this app
AllocConsole();
const bool isConsoleAllocated = AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
@@ -410,16 +393,16 @@ void create_console()
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
setvbuf( stdin, NULL, _IONBF, 0 );
setvbuf( stdout, NULL, _IONBF, 0 );
setvbuf( stderr, NULL, _IONBF, 0 );
setvbuf( stdin, nullptr, _IONBF, 0 );
setvbuf( stdout, nullptr, _IONBF, 0 );
setvbuf( stderr, nullptr, _IONBF, 0 );
return isConsoleAllocated;
}
LLAppViewerWin32::LLAppViewerWin32(const char* cmd_line) :
mCmdLine(cmd_line)
mCmdLine(cmd_line),
mIsConsoleAllocated(false)
{
}
@@ -442,15 +425,6 @@ bool LLAppViewerWin32::init()
LLWinDebug::instance().init();
#endif
#if LL_WINDOWS
#if LL_SEND_CRASH_REPORTS
LLAppViewer* pApp = LLAppViewer::instance();
pApp->initCrashReporting();
#endif
#endif
bool success = LLAppViewer::init();
return success;
@@ -462,18 +436,24 @@ bool LLAppViewerWin32::cleanup()
gDXHardware.cleanup();
if (mIsConsoleAllocated)
{
FreeConsole();
mIsConsoleAllocated = false;
}
return result;
}
bool LLAppViewerWin32::initLogging()
void LLAppViewerWin32::initLoggingAndGetLastDuration()
{
return LLAppViewer::initLogging();
LLAppViewer::initLoggingAndGetLastDuration();
}
void LLAppViewerWin32::initConsole()
{
// pop up debug console
create_console();
mIsConsoleAllocated = create_console();
return LLAppViewer::initConsole();
}
@@ -571,7 +551,7 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp)
}
// Find the system language.
FL_Locale *locale = NULL;
FL_Locale *locale = nullptr;
FL_Success success = FL_FindLocale(&locale, FL_MESSAGES);
if (success != 0)
{
@@ -595,12 +575,6 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp)
bool LLAppViewerWin32::restoreErrorTrap()
{
return true;
//return LLWinDebug::checkExceptionHandler();
}
void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
{
// Singu Note: we don't fork the crash logger on start
}
//virtual
@@ -610,9 +584,9 @@ bool LLAppViewerWin32::sendURLToOtherInstance(const std::string& url)
mbstowcs(window_class, sWindowClass.c_str(), 255);
window_class[255] = 0;
// Use the class instead of the window name.
HWND other_window = FindWindow(window_class, NULL);
HWND other_window = FindWindow(window_class, nullptr);
if (other_window != NULL)
if (other_window != nullptr)
{
LL_DEBUGS() << "Found other window with the name '" << getWindowTitle() << "'" << LL_ENDL;
COPYDATASTRUCT cds;
@@ -638,13 +612,13 @@ std::string LLAppViewerWin32::generateSerialNumber()
DWORD serial = 0;
DWORD flags = 0;
BOOL success = GetVolumeInformation(
L"C:\\",
NULL, // volume name buffer
TEXT("C:\\"),
nullptr, // volume name buffer
0, // volume name buffer size
&serial, // volume serial
NULL, // max component length
nullptr, // max component length
&flags, // file system flags
NULL, // file system name buffer
nullptr, // file system name buffer
0); // file system name buffer size
if (success)
{

View File

@@ -46,22 +46,20 @@ 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;
protected:
virtual bool initLogging(); // 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 restoreErrorTrap();
virtual void initCrashReporting(bool reportFreeze);
bool restoreErrorTrap() override;
virtual bool sendURLToOtherInstance(const std::string& url);
std::string generateSerialNumber();
bool sendURLToOtherInstance(const std::string& url) override;
std::string generateSerialNumber() override;
static const std::string sWindowClass;
@@ -69,6 +67,7 @@ private:
void disableWinErrorReporting();
std::string mCmdLine;
bool mIsConsoleAllocated;
};
#endif // LL_LLAPPVIEWERWIN32_H

View File

@@ -1,418 +0,0 @@
/**
* @file llcrashlogger.cpp
* @brief Crash logger implementation
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llcrashlogger.h"
#include "linden_common.h"
#include "llstring.h"
#include "indra_constants.h" // CRASH_BEHAVIOR_...
#include "llerror.h"
#include "llerrorcontrol.h"
#include "lltimer.h"
#include "lldir.h"
#include "llfile.h"
#include "llsdserialize.h"
#include "lliopipe.h"
#include "llpumpio.h"
#include "llhttpclient.h"
#include "llsdserialize.h"
#include "llproxy.h"
#include "llwindow.h"
#include "lltrans.h"
#include "aistatemachine.h"
#include "boost/filesystem.hpp"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy crashLoggerResponder_timeout;
extern const std::string OLD_LOG_FILE;
class LLCrashLoggerResponder : public LLHTTPClient::ResponderWithResult
{
public:
LLCrashLoggerResponder()
{
}
virtual void httpFailure(void)
{
LL_WARNS() << "Crash report sending failed: " << mReason << LL_ENDL;
}
virtual void httpSuccess(void)
{
std::string msg = "Crash report successfully sent";
if (mContent.has("message"))
{
msg += ": " + mContent["message"].asString();
}
LL_INFOS() << msg << LL_ENDL;
if (mContent.has("report_id"))
{
gSavedSettings.setS32("CrashReportID", mContent["report_id"].asInteger());
}
}
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const
{
return crashLoggerResponder_timeout;
}
virtual char const* getName(void) const
{
return "LLCrashLoggerResponder";
}
};
LLCrashLogger::LLCrashLogger() :
mCrashBehavior(CRASH_BEHAVIOR_ALWAYS_SEND),
mCrashInPreviousExec(false),
mCrashHost("")
{
}
LLCrashLogger::~LLCrashLogger()
{
}
// TRIM_SIZE must remain larger than LINE_SEARCH_SIZE.
const int TRIM_SIZE = 128000;
const int LINE_SEARCH_DIST = 500;
const std::string SKIP_TEXT = "\n ...Skipping... \n";
void trimSLLog(std::string& sllog)
{
if(sllog.length() > TRIM_SIZE * 2)
{
std::string::iterator head = sllog.begin() + TRIM_SIZE;
std::string::iterator tail = sllog.begin() + sllog.length() - TRIM_SIZE;
std::string::iterator new_head = std::find(head, head - LINE_SEARCH_DIST, '\n');
if(new_head != head - LINE_SEARCH_DIST)
{
head = new_head;
}
std::string::iterator new_tail = std::find(tail, tail + LINE_SEARCH_DIST, '\n');
if(new_tail != tail + LINE_SEARCH_DIST)
{
tail = new_tail;
}
sllog.erase(head, tail);
sllog.insert(head, SKIP_TEXT.begin(), SKIP_TEXT.end());
}
}
std::string getStartupStateFromLog(std::string& sllog)
{
std::string startup_state = "STATE_FIRST";
std::string startup_token = "Startup state changing from ";
int index = sllog.rfind(startup_token);
if (index < 0 || index + startup_token.length() > sllog.length()) {
return startup_state;
}
// find new line
char cur_char = sllog[index + startup_token.length()];
std::string::size_type newline_loc = index + startup_token.length();
while(cur_char != '\n' && newline_loc < sllog.length())
{
newline_loc++;
cur_char = sllog[newline_loc];
}
// get substring and find location of " to "
std::string state_line = sllog.substr(index, newline_loc - index);
std::string::size_type state_index = state_line.find(" to ");
startup_state = state_line.substr(state_index + 4, state_line.length() - state_index - 4);
return startup_state;
}
bool miniDumpExists(const std::string& dumpDir)
{
bool found = false;
try
{
if (!boost::filesystem::exists(dumpDir))
{
return false;
}
boost::filesystem::directory_iterator end_itr;
for (boost::filesystem::directory_iterator i(dumpDir); i != end_itr; ++i)
{
if (!boost::filesystem::is_regular_file(i->status())) continue;
if (".dmp" == i->path().extension())
{
found = true;
break;
}
}
}
catch (const boost::filesystem::filesystem_error& e)
{
LL_WARNS() << "Failed to determine existance of the minidump file: '" + e.code().message() +"'" << LL_ENDL;
}
return found;
}
bool LLCrashLogger::readDebugFromXML(LLSD& dest, const std::string& filename )
{
std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,filename);
std::ifstream debug_log_file(db_file_name.c_str());
// Look for it in the debug_info.log file
if (debug_log_file.is_open())
{
LLSDSerialize::fromXML(dest, debug_log_file);
debug_log_file.close();
return true;
}
return false;
}
void LLCrashLogger::mergeLogs( LLSD src_sd )
{
LLSD::map_iterator iter = src_sd.beginMap();
LLSD::map_iterator end = src_sd.endMap();
for( ; iter != end; ++iter)
{
mDebugLog[iter->first] = iter->second;
}
}
bool LLCrashLogger::readMinidump(std::string minidump_path)
{
size_t length=0;
std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary);
if(minidump_stream.is_open())
{
minidump_stream.seekg(0, std::ios::end);
length = (size_t)minidump_stream.tellg();
minidump_stream.seekg(0, std::ios::beg);
LLSD::Binary data;
data.resize(length);
minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length);
minidump_stream.close();
mCrashInfo["Minidump"] = data;
}
return (length>0?true:false);
}
void LLCrashLogger::gatherFiles()
{
LL_INFOS() << "Gathering logs..." << LL_ENDL;
LLSD static_sd;
LLSD dynamic_sd;
bool has_logs = readDebugFromXML( static_sd, "static_debug_info.log" );
has_logs |= readDebugFromXML( dynamic_sd, "dynamic_debug_info.log" );
if ( has_logs )
{
mDebugLog = static_sd;
mergeLogs(dynamic_sd);
mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean();
mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString();
mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString();
if(mDebugLog.has("CAFilename"))
{
LLCurl::setCAFile(mDebugLog["CAFilename"].asString());
}
else
{
LLCurl::setCAFile(gDirUtilp->getCAFile());
}
LL_INFOS() << "Using log file from debug log " << mFileMap["SecondLifeLog"] << LL_ENDL;
LL_INFOS() << "Using settings file from debug log " << mFileMap["SettingsXml"] << LL_ENDL;
}
else
{
// Figure out the filename of the second life log
LLCurl::setCAFile(gDirUtilp->getCAFile());
mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log");
mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
}
if(mCrashInPreviousExec)
{
// Restarting after freeze.
// Replace the log file ext with .old, since the
// instance that launched this process has overwritten
// SecondLife.log
std::string log_filename = mFileMap["SecondLifeLog"];
log_filename.replace(log_filename.size() - 4, 4, ".old");
mFileMap["SecondLifeLog"] = log_filename;
}
gatherPlatformSpecificFiles();
mCrashInfo["DebugLog"] = mDebugLog;
mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"stats.log");
// Singu Note: we have just started again, log has been renamed
mFileMap["SecondLifeLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, OLD_LOG_FILE);
LL_INFOS() << "Encoding files..." << LL_ENDL;
for(std::map<std::string, std::string>::iterator itr = mFileMap.begin(); itr != mFileMap.end(); ++itr)
{
std::ifstream f((*itr).second.c_str());
if(!f.is_open())
{
LL_INFOS() << "Can't find file " << (*itr).second << LL_ENDL;
continue;
}
std::stringstream s;
s << f.rdbuf();
std::string crash_info = s.str();
if(itr->first == "SecondLifeLog")
{
if(!mCrashInfo["DebugLog"].has("StartupState"))
{
mCrashInfo["DebugLog"]["StartupState"] = getStartupStateFromLog(crash_info);
}
trimSLLog(crash_info);
}
mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info));
}
std::string minidump_path;
// Add minidump as binary.
bool has_minidump = mDebugLog.has("MinidumpPath");
if (has_minidump)
minidump_path = mDebugLog["MinidumpPath"].asString();
if (has_minidump)
{
has_minidump = readMinidump(minidump_path);
}
if (!has_minidump) //Viewer was probably so hosed it couldn't write remaining data. Try brute force.
{
//Look for a filename at least 30 characters long in the dump dir which contains the characters MDMP as the first 4 characters in the file.
typedef std::vector<std::string> vec;
std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"");
vec file_vec = gDirUtilp->getFilesInDir(pathname);
for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter)
{
if ( ( iter->length() > 30 ) && (iter->rfind(".log") != (iter->length()-4) ) )
{
std::string fullname = pathname + *iter;
std::ifstream fdat( fullname.c_str(), std::ifstream::binary);
if (fdat)
{
char buf[5];
fdat.read(buf,4);
fdat.close();
if (!strncmp(buf,"MDMP",4))
{
minidump_path = *iter;
has_minidump = readMinidump(fullname);
mDebugLog["MinidumpPath"] = fullname;
}
}
}
}
}
}
LLSD LLCrashLogger::constructPostData()
{
return mCrashInfo;
}
bool LLCrashLogger::sendCrashLog(std::string dump_dir)
{
gDirUtilp->setDumpDir( dump_dir );
std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SingularityCrashReport");
std::string report_file = dump_path + ".log";
gatherFiles();
LLSD post_data;
post_data = constructPostData();
LL_INFOS() << "Sending reports..." << LL_ENDL;
std::ofstream out_file(report_file.c_str());
LLSDSerialize::toPrettyXML(post_data, out_file);
out_file.close();
LLHTTPClient::post(mCrashHost, post_data, new LLCrashLoggerResponder());
return true;
}
void LLCrashLogger::checkCrashDump()
{
#if LL_SEND_CRASH_REPORTS
// 0 - ask, 1 - always send, 2 - never send
S32 pref = gSavedSettings.getS32("CrashSubmitBehavior");
if (pref == 2) return; //never send
mCrashHost = gSavedSettings.getString("CrashHostUrl");
std::string dumpDir = gDirUtilp->getDumpDir();
// Do we have something to send, and somewhere to send it
if (!mCrashHost.empty() && miniDumpExists(dumpDir))
{
if (pref == 1) // always send
{
sendCrashLog(dumpDir);
}
else // ask
{
U32 response = OSMessageBox(LLTrans::getString("MBFrozenCrashed"), LLTrans::getString("MBAlert"), OSMB_YESNO);
if (response == OSBTN_YES)
{
sendCrashLog(dumpDir);
}
}
}
#endif
}

View File

@@ -1,67 +0,0 @@
/**
* @file llcrashlogger.h
* @brief Crash Logger Definition
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLCRASHLOGGER_H
#define LLCRASHLOGGER_H
#include <vector>
#include "linden_common.h"
#include "llapp.h"
#include "llsd.h"
#include "llcontrol.h"
class LLCrashLogger
{
public:
LLCrashLogger();
virtual ~LLCrashLogger();
S32 loadCrashBehaviorSetting();
bool readDebugFromXML(LLSD& dest, const std::string& filename );
void gatherFiles();
void mergeLogs( LLSD src_sd );
virtual void gatherPlatformSpecificFiles() {}
bool saveCrashBehaviorSetting(S32 crash_behavior);
bool sendCrashLog(std::string dump_dir);
LLSD constructPostData();
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
S32 getCrashBehavior() { return mCrashBehavior; }
bool readMinidump(std::string minidump_path);
void checkCrashDump();
protected:
S32 mCrashBehavior;
BOOL mCrashInPreviousExec;
std::map<std::string, std::string> mFileMap;
std::string mGridName;
std::string mProductName;
LLSD mCrashInfo;
std::string mCrashHost;
LLSD mDebugLog;
};
#endif //LLCRASHLOGGER_H

View File

@@ -87,7 +87,7 @@ BOOL LLPanelGeneral::postBuild()
childSetValue("ui_auto_scale", gSavedSettings.getBOOL("UIAutoScale"));
LLComboBox* crash_behavior_combobox = getChild<LLComboBox>("crash_behavior_combobox");
crash_behavior_combobox->setCurrentByIndex(gSavedSettings.getS32(CRASH_BEHAVIOR_SETTING));
crash_behavior_combobox->setValue(gSavedSettings.getS32("CrashSubmitBehavior"));
childSetValue("language_combobox", gSavedSettings.getString("Language"));
@@ -163,7 +163,7 @@ void LLPanelGeneral::apply()
gSavedSettings.setString("Language", childGetValue("language_combobox"));
LLComboBox* crash_behavior_combobox = getChild<LLComboBox>("crash_behavior_combobox");
gSavedSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior_combobox->getCurrentIndex());
gSavedSettings.setS32("CrashSubmitBehavior", crash_behavior_combobox->getValue());
}
void LLPanelGeneral::cancel()

View File

@@ -94,7 +94,6 @@ AIThreadSafeDC<settings_map_type> gSettings;
LLControlGroup gSavedSettings("Global"); // saved at end of session
LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
LLControlGroup gColors("Colors"); // saved at end of session
LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session
std::string gLastRunVersion;

View File

@@ -62,9 +62,6 @@ void create_graphics_group(LLControlGroup& group);
// Read-only
extern LLControlGroup gColors;
// Saved at end of session
extern LLControlGroup gCrashSettings;
// Set after settings loaded
extern std::string gLastRunVersion;

View File

@@ -11450,6 +11450,19 @@ Do you wish to export anyway?
Object successfully exported to: [FILENAME]
</notification>
<notification
icon="alertmodal.tga"
name="SubmitCrashReports"
type="alertmodal">
Would you like to help improve [SHORT_APP_NAME] by sending crash reports?
(You can change your answer in Preferences -> General -> Crash reports)
<usetemplate
name="okcancelbuttons"
notext="No"
yestext="Yes"/>
</notification>
<notification
icon="alertmodal.tga"
name="SupportChatShowInfo"

View File

@@ -67,9 +67,8 @@
</combo_box>
<string name="region_name_prompt">&lt;Type region name&gt;</string>
<combo_box bottom="-328" height="18" left="103" name="crash_behavior_combobox" width="140">
<combo_item name="Askbeforesending" value="Ask before sending">Ask before sending</combo_item>
<combo_item name="Alwayssend" value="Always send">Always send</combo_item>
<combo_item name="Neversend" value="Never send">Never send</combo_item>
<combo_item name="Neversend" value="0">Never send</combo_item>
<combo_item name="Alwayssend" value="1">Always send</combo_item>
</combo_box>
<check_box bottom="-385" height="16" initial_value="false" label="Share language with objects" left="101" name="language_is_public" tool_tip="This lets in-world objects know your preferred language."/>
<button bottom="-425" height="25" label="Reset All Settings" name="clear_settings" width="200" />

View File

@@ -3833,6 +3833,7 @@ This can be because you somehow have multiple copies running, or your system inc
If this message persists, restart your computer and try again.
If it continues to persist, you may need to completely uninstall [APP_NAME] and reinstall it.
</string>
<string name="MBFatalError">Fatal Error. Crash and Loop?</string>
<string name="MBAlreadyRunning">
[APP_NAME] is already running.
Check your task bar for a minimized copy of the program.

View File

@@ -525,6 +525,12 @@ class WindowsManifest(ViewerManifest):
except:
print "Skipping msvc redist files"
# For crashpad
with self.prefix(src=pkgbindir):
self.path("crashpad_handler.exe")
if not self.is_packaging_viewer():
self.path("crashpad_handler.pdb")
self.path(src="licenses-win32.txt", dst="licenses.txt")
self.path("featuretable.txt")