From 719edddf0498752a0295502d62710823d1a72cc7 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 21 May 2010 09:38:29 -0700 Subject: Switch Darwin to use breakpad minidump rather than os generated crash stack. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/llapp.cpp | 51 ++++++++++++++++++++++++++++++++++- indra/llcommon/llapp.h | 11 ++++++-- indra/llcrashlogger/llcrashlogger.cpp | 21 +++++++++++++++ indra/newview/llappviewer.cpp | 2 ++ 5 files changed, 83 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3c689930b8..051e198e75 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -259,6 +259,7 @@ endif(LLCOMMON_LINK_SHARED) target_link_libraries( llcommon + exception_handler ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6b2d1b7c20..e766563c6f 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -56,6 +56,11 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); # include // for fork() void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); + +// Called by breakpad exception handler after the minidump has been generated. +bool darwin_post_minidump_callback(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded); # if LL_DARWIN /* OSX doesn't support SIGRT* */ S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -123,7 +128,10 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - + + mExceptionHandler = 0; + + memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH); } LLApp::LLApp(LLErrorThread *error_thread) : @@ -152,6 +160,8 @@ LLApp::~LLApp() delete mThreadErrorp; mThreadErrorp = NULL; } + + if(mExceptionHandler != 0) delete mExceptionHandler; LLCommon::cleanupClass(); } @@ -285,6 +295,15 @@ void LLApp::setupErrorHandling() setup_signals(); + +#ifdef LL_DARWIN + // Add google breakpad exception handler configured for Darwin. + if(mExceptionHandler == 0) + { + std::string dumpPath = "/tmp/"; + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &darwin_post_minidump_callback, 0, true); + } +#endif #endif startErrorThread(); @@ -587,6 +606,7 @@ void setup_signals() // Asynchronous signals that result in core sigaction(SIGQUIT, &act, NULL); + } void clear_signals() @@ -766,3 +786,32 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } #endif // !WINDOWS + +bool darwin_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: /.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()->minidump_path; + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + strncpy(path, dump_dir, remaining); + remaining -= dirPathLength; + path += dirPathLength; + strncpy(path, minidump_id, remaining); + remaining -= idLength; + path += idLength; + strncpy(path, ".dmp", remaining); + + llinfos << "generated minidump: " << LLApp::instance()->minidump_path << llendl; + LLApp::runErrorHandler(); + return true; +} diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index e5b8edf9c3..cd17532203 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -38,6 +38,8 @@ #include "llsd.h" #include "lloptioninterface.h" +#include "exception_handler.h" + // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -228,6 +230,8 @@ public: void setErrorHandler(LLAppErrorHandler handler); void setSyncErrorHandler(LLAppErrorHandler handler); + static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. + static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. //@} #if !LL_WINDOWS @@ -265,6 +269,9 @@ public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map + // Contains the path to minidump file after a crash. + static const U32 MAX_MINDUMP_PATH_LENGTH = 256; + char minidump_path[MAX_MINDUMP_PATH_LENGTH]; protected: static void setStatus(EAppStatus status); // Use this to change the application status. @@ -286,8 +293,6 @@ protected: private: void startErrorThread(); - static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. - static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. // *NOTE: On Windows, we need a routine to reset the structured // exception handler when some evil driver has taken it over for @@ -315,6 +320,8 @@ private: private: // the static application instance if it was created. static LLApp* sApplication; + + google_breakpad::ExceptionHandler * mExceptionHandler; #if !LL_WINDOWS diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index c1022c1195..8f5aa5ab2d 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -274,6 +274,27 @@ void LLCrashLogger::gatherFiles() mCrashInfo[(*itr).first] = rawstr_to_utf8(crash_info); } + + // Add minidump as binary. + std::string minidump_path = mDebugLog["MinidumpPath"]; + if(minidump_path != "") + { + 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); + size_t length = minidump_stream.tellg(); + minidump_stream.seekg(0, std::ios::beg); + + LLSD::Binary data; + data.resize(length); + + minidump_stream.read(reinterpret_cast(&(data[0])),length); + minidump_stream.close(); + + mCrashInfo["Minidump"] = data; + } + } } LLSD LLCrashLogger::constructPostData() diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f7f7cb599e..56486c788b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2587,6 +2587,8 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); + if(pApp->minidump_path[0] != 0) gDebugInfo["MinidumpPath"] = pApp->minidump_path; + if(gLogoutInProgress) { gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; -- cgit v1.2.3 From fa06293a4c637b31094a8c6907982851d4d0b464 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 21 May 2010 11:48:07 -0700 Subject: Added call to use_prebuilt_binary for google-breakpad so it actually gets installed by install.py. --- indra/cmake/GoogleBreakpad.cmake | 11 +++++++++++ indra/llcommon/CMakeLists.txt | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 indra/cmake/GoogleBreakpad.cmake (limited to 'indra') diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake new file mode 100644 index 0000000000..e45518ef56 --- /dev/null +++ b/indra/cmake/GoogleBreakpad.cmake @@ -0,0 +1,11 @@ +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") + # *TODO - implement this include(FindGoogleBreakpad) +else (STANDALONE) + use_prebuilt_binary(google_breakpad) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) +endif (STANDALONE) + diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 051e198e75..2fcb04321c 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -9,6 +9,7 @@ include(Linking) include(Boost) include(Pth) include(LLSharedLibs) +include(GoogleBreakpad) include(GooglePerfTools) include(Copy3rdPartyLibs) @@ -259,7 +260,7 @@ endif(LLCOMMON_LINK_SHARED) target_link_libraries( llcommon - exception_handler + ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} -- cgit v1.2.3 From ba809777e5ba240622f6c67ff400733899c275bf Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 21 May 2010 14:39:55 -0700 Subject: New google breakpad package for windows with winsock2 fix, and DLL CRT library usage. Also moved headers into libraries/include/google_breakpad. Mac and linux packages to come shortly. --- indra/llcommon/llapp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index cd17532203..348eec0c48 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -38,7 +38,7 @@ #include "llsd.h" #include "lloptioninterface.h" -#include "exception_handler.h" +#include "google_breakpad/exception_handler.h" // Forward declarations template class LLAtomic32; -- cgit v1.2.3 From 95d7aab108516826f459c7202ea5941e94d0c5eb Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 21 May 2010 15:48:40 -0700 Subject: New windows google_breakpad package with GUIDString class included in common.lib. I've confimred that llcommon links now. --- indra/cmake/GoogleBreakpad.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake index e45518ef56..3aac79eeeb 100644 --- a/indra/cmake/GoogleBreakpad.cmake +++ b/indra/cmake/GoogleBreakpad.cmake @@ -6,6 +6,6 @@ if (STANDALONE) # *TODO - implement this include(FindGoogleBreakpad) else (STANDALONE) use_prebuilt_binary(google_breakpad) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) endif (STANDALONE) -- cgit v1.2.3 From d9fee67f976b72a3c6145627638e4e15a8f54d7e Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 21 May 2010 19:09:53 -0700 Subject: VPLAT-237 Linux client library package for google_breakpad. --- indra/cmake/Copy3rdPartyLibs.cmake | 3 ++- indra/cmake/GoogleBreakpad.cmake | 3 +++ indra/newview/viewer_manifest.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index faf9da8b14..937d3c6384 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -19,7 +19,7 @@ if(WINDOWS) set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32") set(vivox_files SLVoice.exe - libsndfile-1.dll + libsndfile-1.dll vivoxplatform.dll vivoxsdk.dll ortp.dll @@ -216,6 +216,7 @@ elseif(LINUX) libapr-1.so.0 libaprutil-1.so.0 libatk-1.0.so + libbreakpad_client.so.0 libcrypto.so.0.9.7 libdb-4.2.so libexpat.so diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake index 3aac79eeeb..0b9f4a00d0 100644 --- a/indra/cmake/GoogleBreakpad.cmake +++ b/indra/cmake/GoogleBreakpad.cmake @@ -7,5 +7,8 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(google_breakpad) set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) + if (LINUX) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) + endif (LINUX) endif (STANDALONE) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 2a966f4adf..96541088b5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -888,6 +888,7 @@ class Linux_i686Manifest(LinuxManifest): if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") + self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0") self.path("libdb-4.2.so") self.path("libcrypto.so.0.9.7") self.path("libexpat.so.1") -- cgit v1.2.3 From 1077ab49c171c0f310f9b76b360ea2ad162a31ff Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 15:19:33 -0700 Subject: Just enough hackery to get minidumps into Wind'ohs crash reports. Code clean up needed. --- indra/cmake/GoogleBreakpad.cmake | 31 ++++++++++-------- indra/llcommon/llapp.cpp | 67 ++++++++++++++++++++++++++++++++++++++ indra/llcommon/llapp.h | 6 ++-- indra/newview/llappviewerwin32.cpp | 5 +-- indra/newview/llwindebug.cpp | 28 +++++++--------- 5 files changed, 102 insertions(+), 35 deletions(-) (limited to 'indra') diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake index 0b9f4a00d0..b21b733500 100644 --- a/indra/cmake/GoogleBreakpad.cmake +++ b/indra/cmake/GoogleBreakpad.cmake @@ -1,14 +1,17 @@ -# -*- cmake -*- -include(Prebuilt) - -if (STANDALONE) - MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") - # *TODO - implement this include(FindGoogleBreakpad) -else (STANDALONE) - use_prebuilt_binary(google_breakpad) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) - if (LINUX) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) - endif (LINUX) -endif (STANDALONE) - +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") + # *TODO - implement this include(FindGoogleBreakpad) +else (STANDALONE) + use_prebuilt_binary(google_breakpad) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) + if(WINDOWS) + list(APPEND BREAKPAD_EXCEPTION_HANDLER_LIBRARIES crash_generation_client common) + endif(WINDOWS) + if (LINUX) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) + endif (LINUX) +endif (STANDALONE) + diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index e766563c6f..e22ff869e7 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -30,6 +30,8 @@ * $/LicenseInfo$ */ +#include + #include "linden_common.h" #include "llapp.h" @@ -43,6 +45,8 @@ #include "llstl.h" // for DeletePointer() #include "lleventtimer.h" +#include "google_breakpad/exception_handler.h" + // // Signal handling // @@ -51,6 +55,12 @@ #if LL_WINDOWS 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 # include // for fork() @@ -285,6 +295,13 @@ void LLApp::setupErrorHandling() // The viewer shouldn't be affected, sicne its a windowed app. SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); + if(mExceptionHandler == 0) + { + llwarns << "adding breakpad exception handler" << llendl; + mExceptionHandler = new google_breakpad::ExceptionHandler( + L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL); + } + #else // // Start up signal handling. @@ -815,3 +832,53 @@ bool darwin_post_minidump_callback(const char *dump_dir, LLApp::runErrorHandler(); return true; } + +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()->minidump_path; + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + size_t bytesUsed; + + bytesUsed = wcstombs(path, dump_path, static_cast(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + if(remaining > 0) + { + bytesUsed = wcstombs(path, minidump_id, static_cast(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + } + if(remaining > 0) + { + strncpy(path, ".dmp", remaining); + } + + llinfos << "generated minidump: " << LLApp::instance()->minidump_path << llendl; + // *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 + llinfos << "Entering Windows Exception Handler..." << llendl; + + if (LLApp::isError()) + { + llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; + } + + // 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); + } + + return true; +} diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 348eec0c48..725c13866f 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -38,8 +38,6 @@ #include "llsd.h" #include "lloptioninterface.h" -#include "google_breakpad/exception_handler.h" - // Forward declarations template class LLAtomic32; typedef LLAtomic32 LLAtomicU32; @@ -68,6 +66,10 @@ public: }; #endif +namespace google_breakpad { + class ExceptionHandler; // See exception_handler.h +} + class LL_COMMON_API LLApp : public LLOptionInterface { friend class LLErrorThread; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 60a6d2f072..4bee8d9ac5 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -529,8 +529,9 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } bool LLAppViewerWin32::restoreErrorTrap() -{ - return LLWinDebug::checkExceptionHandler(); +{ + return true; + //return LLWinDebug::checkExceptionHandler(); } void LLAppViewerWin32::handleSyncCrashTrace() diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index 59bc9dc62b..9f8585f163 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -718,7 +718,8 @@ BOOL PreventSetUnhandledExceptionFilter() // static void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) { - + return; +#if 0 static bool s_first_run = true; // Load the dbghelp dll now, instead of waiting for the crash. // Less potential for stack mangling @@ -762,34 +763,27 @@ void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(filter_func); - - // *REMOVE:Mani - //PreventSetUnhandledExceptionFilter(); + PVOID added_filter = + AddVectoredExceptionHandler(0, filter_func); - if(prev_filter != gFilterFunc) + if(added_filter == 0) { LL_WARNS("AppInit") - << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; + << "Failed to add exception handler (" << added_filter << ") !" << LL_ENDL; } gFilterFunc = filter_func; +#endif } bool LLWinDebug::checkExceptionHandler() { bool ok = true; - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(gFilterFunc); - if (prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; - ok = false; - } + RemoveVectoredExceptionHandler(gFilterFunc); + PVOID filter = AddVectoredExceptionHandler(0, gFilterFunc); - if (prev_filter == NULL) + if (filter == NULL) { ok = FALSE; if (gFilterFunc == NULL) @@ -798,7 +792,7 @@ bool LLWinDebug::checkExceptionHandler() } else { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; + LL_WARNS("AppInit") << "Failed to add exception handler (" << (void *)gFilterFunc << ")!" << LL_ENDL; } } -- cgit v1.2.3 From 28bff2cd99ec97d50f07b620f489a9d8745d3add Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Mon, 24 May 2010 15:42:22 -0700 Subject: Fix for mac build failing to find google_breakpad client libraries. --- indra/cmake/GoogleBreakpad.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake index 0b9f4a00d0..8270c0fabb 100644 --- a/indra/cmake/GoogleBreakpad.cmake +++ b/indra/cmake/GoogleBreakpad.cmake @@ -6,9 +6,14 @@ if (STANDALONE) # *TODO - implement this include(FindGoogleBreakpad) else (STANDALONE) use_prebuilt_binary(google_breakpad) - set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) + 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 common) + endif (WINDOWS) endif (STANDALONE) -- cgit v1.2.3 From f24c312f8369fbc6ec4eb0607e7e8ea636aacb82 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 15:59:26 -0700 Subject: so long llwindebug, we hardly knew ye. --- indra/newview/CMakeLists.txt | 3 - indra/newview/llappviewer.cpp | 5 - indra/newview/llappviewerwin32.cpp | 55 --- indra/newview/llstartup.cpp | 1 - indra/newview/llviewermessage.cpp | 4 - indra/newview/llwindebug.cpp | 906 ------------------------------------- indra/newview/llwindebug.h | 75 --- 7 files changed, 1049 deletions(-) delete mode 100644 indra/newview/llwindebug.cpp delete mode 100644 indra/newview/llwindebug.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f2bed843c9..4571aa1074 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1055,7 +1055,6 @@ set(viewer_HEADER_FILES llwearabletype.h llweb.h llwind.h - llwindebug.h llwlanimator.h llwldaycycle.h llwlparammanager.h @@ -1130,12 +1129,10 @@ endif (LINUX) if (WINDOWS) list(APPEND viewer_SOURCE_FILES llappviewerwin32.cpp - llwindebug.cpp ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h - llwindebug.h ) # precompiled header configuration diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 56486c788b..e9ec0b8b77 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -104,7 +104,6 @@ #include #if LL_WINDOWS - #include "llwindebug.h" # include // For _SH_DENYWR in initMarkerFile #else # include // For initMarkerFile support @@ -3288,10 +3287,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; -#if LL_WINDOWS - // Generates the minidump. - LLWinDebug::generateCrashStacks(NULL); -#endif LLAppViewer::handleSyncViewerCrash(); LLAppViewer::handleViewerCrash(); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4bee8d9ac5..88d8dba8af 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -57,8 +57,6 @@ #include "llweb.h" #include "llsecondlifeurls.h" -#include "llwindebug.h" - #include "llviewernetwork.h" #include "llmd5.h" #include "llfindlocale.h" @@ -81,51 +79,6 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *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 - _tprintf( _T("Entering Windows Exception Handler...\n") ); - llinfos << "Entering Windows Exception Handler..." << llendl; - - // Make sure the user sees something to indicate that the app crashed. - LONG retval; - - if (LLApp::isError()) - { - _tprintf( _T("Got another fatal signal while in the error handler, die now!\n") ); - llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; - } - - // Generate a minidump if we can. - // Before we wake the error thread... - // Which will start the crash reporting. - LLWinDebug::generateCrashStacks(exception_infop); - - // 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); - } - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; -} - // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -191,8 +144,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - - LLWinDebug::initExceptionHandler(viewer_windows_exception_handler); viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); @@ -405,12 +356,6 @@ bool LLAppViewerWin32::cleanup() bool LLAppViewerWin32::initLogging() { - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // *NOTE: This should happen before the we send a 'previous instance froze' - // crash report, but it must happen after we initialize the DirUtil. - LLWinDebug::clearCrashStacks(); - return LLAppViewer::initLogging(); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a84bb98a90..e43b3b84c8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,7 +199,6 @@ #include "llstartuplistener.h" #if LL_WINDOWS -#include "llwindebug.h" #include "lldxhardware.h" #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fb87e2d3b9..c677406223 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -110,10 +110,6 @@ #include // #include -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h" // For the invalid message handler -#endif - #include "llnotificationmanager.h" // #if LL_MSVC diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp deleted file mode 100644 index 9f8585f163..0000000000 --- a/indra/newview/llwindebug.cpp +++ /dev/null @@ -1,906 +0,0 @@ -/** - * @file llwindebug.cpp - * @brief Windows debugging functions - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include -#include -#include "llwindebug.h" -#include "llviewercontrol.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" - -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - - -/* -LLSD Block for Windows Dump Information - - - Platform - - Process - - Module - - DateModified - - ExceptionCode - - ExceptionRead/WriteAddress - - Instruction - - Registers - - - EIP - ... - - - Call Stack - - - - ModuleName - - ModuleBaseAddress - - ModuleOffsetAddress - - Parameters - - - - - - - - - -*/ - - -extern void (*gCrashCallback)(void); - -// based on dbghelp.h -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - -MINIDUMPWRITEDUMP f_mdwp = NULL; - -#undef UNICODE - -static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; - -HMODULE hDbgHelp; - -// Tool Help functions. -typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); -typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); -typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - -CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; -MODULE32_FIRST Module32First_; -MODULE32_NEST Module32Next_; - -#define DUMP_SIZE_MAX 8000 //max size of our dump -#define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls -#define NL L"\r\n" //new line - - -typedef struct STACK -{ - STACK * Ebp; - PBYTE Ret_Addr; - DWORD Param[0]; -} STACK, * PSTACK; - -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr); -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info); - -void printError( CHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg ); -} - -BOOL GetProcessThreadIDs(DWORD process_id, std::vector& thread_ids) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if( hThreadSnap == INVALID_HANDLE_VALUE ) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if( !Thread32First( hThreadSnap, &te32 ) ) - { - printError( "Thread32First" ); // Show cause of failure - CloseHandle( hThreadSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if( te32.th32OwnerProcessID == process_id ) - { - thread_ids.push_back(te32.th32ThreadID); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - -// Don't forget to clean up the snapshot object. - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -BOOL GetThreadCallStack(DWORD thread_id, LLSD& info) -{ - if(GetCurrentThreadId() == thread_id) - { - // Early exit for the current thread. - // Suspending the current thread would be a bad idea. - // Plus you can't retrieve a valid current thread context. - return false; - } - - HANDLE thread_handle = INVALID_HANDLE_VALUE; - thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); - if(INVALID_HANDLE_VALUE == thread_handle) - { - return FALSE; - } - - BOOL result = false; - if(-1 != SuspendThread(thread_handle)) - { - CONTEXT context_struct; - context_struct.ContextFlags = CONTEXT_FULL; - if(GetThreadContext(thread_handle, &context_struct)) - { - Get_Call_Stack(NULL, &context_struct, info); - result = true; - } - ResumeThread(thread_handle); - } - else - { - // Couldn't suspend thread. - } - - CloseHandle(thread_handle); - return result; -} - - -//Windows Call Stack Construction idea from -//http://www.codeproject.com/tools/minidump.asp - -//**************************************************************************************** -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr) -//**************************************************************************************** -// Find module by Ret_Addr (address in the module). -// Return Module_Name (full path) and Module_Addr (start address). -// Return TRUE if found. -{ - MODULEENTRY32 M = {sizeof(M)}; - HANDLE hSnapshot; - - bool found = false; - - if (CreateToolhelp32Snapshot_) - { - hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); - - if ((hSnapshot != INVALID_HANDLE_VALUE) && - Module32First_(hSnapshot, &M)) - { - do - { - if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) - { - lstrcpyn(Module_Name, M.szExePath, MAX_PATH); - Module_Addr = M.modBaseAddr; - found = true; - break; - } - } while (Module32Next_(hSnapshot, &M)); - } - - CloseHandle(hSnapshot); - } - - return found; -} //Get_Module_By_Ret_Addr - -bool has_valid_call_before(PDWORD cur_stack_loc) -{ - PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1); - PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2); - PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5); - PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6); - - // make sure we can read it - if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE))) - { - return false; - } - - // check for 9a + 4 bytes - if(*p_fifth_byte == 0x9A) - { - return true; - } - - // Check for E8 + 4 bytes and last byte is 00 or FF - if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF)) - { - return true; - } - - // the other is six bytes - if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF) - { - return true; - } - - return false; -} - -PBYTE get_valid_frame(PBYTE esp) -{ - PDWORD cur_stack_loc = NULL; - const int max_search = 400; - WCHAR module_name[MAX_PATH]; - PBYTE module_addr = 0; - - // round to highest multiple of four - esp = (esp + (4 - ((int)esp % 4)) % 4); - - // scroll through stack a few hundred places. - for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1) - { - // if you can read the pointer, - if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD))) - { - continue; - } - - // check if it's in a module - if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr)) - { - continue; - } - - // check if the code before the instruction ptr is a call - if(!has_valid_call_before(cur_stack_loc)) - { - continue; - } - - // if these all pass, return that ebp, otherwise continue till we're dead - return (PBYTE)(cur_stack_loc - 1); - } - - return NULL; -} - -bool shouldUseStackWalker(PSTACK Ebp, int max_depth) -{ - WCHAR Module_Name[MAX_PATH]; - PBYTE Module_Addr = 0; - int depth = 0; - - while (depth < max_depth) - { - if (IsBadReadPtr(Ebp, sizeof(PSTACK)) || - IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || - Ebp->Ebp < Ebp || - Ebp->Ebp - Ebp > 0xFFFFFF || - IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) || - !Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - return true; - } - depth++; - Ebp = Ebp->Ebp; - } - - return false; -} - -//****************************************************************** -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info) -//****************************************************************** -// Fill Str with call stack info. -// pException can be either GetExceptionInformation() or NULL. -// If pException = NULL - get current call stack. -{ - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr = 0; - LLSD params; - PBYTE Esp = NULL; - LLSD tmp_info; - - bool fake_frame = false; - bool ebp_used = false; - const int HEURISTIC_MAX_WALK = 20; - int heuristic_walk_i = 0; - int Ret_Addr_I = 0; - - STACK Stack = {0, 0}; - PSTACK Ebp; - - if (exception_record && context_record) //fake frame for exception address - { - Stack.Ebp = (PSTACK)(context_record->Ebp); - Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; - Ebp = &Stack; - Esp = (PBYTE) context_record->Esp; - fake_frame = true; - } - else if(context_record) - { - Ebp = (PSTACK)(context_record->Ebp); - Esp = (PBYTE)(context_record->Esp); - } - else - { - Ebp = (PSTACK)&exception_record - 1; //frame addr of Get_Call_Stack() - Esp = (PBYTE)&exception_record; - - // Skip frame of Get_Call_Stack(). - if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) - Ebp = Ebp->Ebp; //caller ebp - } - - // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. - // Break trace on wrong stack frame. - for (Ret_Addr_I = 0; - heuristic_walk_i < HEURISTIC_MAX_WALK && - Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); - Ret_Addr_I++) - { - // If module with Ebp->Ret_Addr found. - if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); - tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; - tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); - - // Save 5 params of the call. We don't know the real number of params. - if (fake_frame && !Ret_Addr_I) //fake frame for exception address - params[0] = "Exception Offset"; - else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) - { - for(int j = 0; j < 5; ++j) - { - params[j] = (int)Ebp->Param[j]; - } - } - tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; - } - - tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; - - // get ready for next frame - // Set ESP to just after return address. Not the real esp, but just enough after the return address - if(!fake_frame) { - Esp = (PBYTE)Ebp + 8; - } - else - { - fake_frame = false; - } - - // is next ebp valid? - // only run if we've never found a good ebp - // and make sure the one after is valid as well - if( !ebp_used && - shouldUseStackWalker(Ebp, 2)) - { - heuristic_walk_i++; - PBYTE new_ebp = get_valid_frame(Esp); - if (new_ebp != NULL) - { - Ebp = (PSTACK)new_ebp; - } - } - else - { - ebp_used = true; - Ebp = Ebp->Ebp; - } - } -/* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer - // Now go back through and edit out heuristic stacks that could very well be bogus. - // Leave the top and the last 3 stack chosen by the heuristic, however. - if(heuristic_walk_i > 2) - { - info["CallStack"][0] = tmp_info["CallStack"][0]; - std::string ttest = info["CallStack"][0]["ModuleName"]; - for(int cur_frame = 1; - (cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); - ++cur_frame) - { - // edit out the middle heuristic found frames - info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; - } - } - else - { - info = tmp_info; - } -*/ - info = tmp_info; - info["HeuristicWalkI"] = heuristic_walk_i; - info["EbpUsed"] = ebp_used; - -} //Get_Call_Stack - -//*********************************** -void WINAPI Get_Version_Str(LLSD& info) -//*********************************** -// Fill Str with Windows version. -{ - OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later - - if (!GetVersionEx((POSVERSIONINFO)&V)) - { - ZeroMemory(&V, sizeof(V)); - V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx((POSVERSIONINFO)&V); - } - - if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) - V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx - - info["Platform"] = llformat("Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,... - V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType); -} //Get_Version_Str - -//************************************************************* -LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) -//************************************************************* -// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. -{ - LLSD info; - LPWSTR Str; - int Str_Len; -// int i; - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr; - HANDLE hFile; - FILETIME Last_Write_Time; - FILETIME Local_File_Time; - SYSTEMTIME T; - - Str = new WCHAR[DUMP_SIZE_MAX]; - Str_Len = 0; - if (!Str) - return NULL; - - Get_Version_Str(info); - - GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); - info["ThreadID"] = (S32)GetCurrentThreadId(); - - // If exception occurred. - if (pException) - { - EXCEPTION_RECORD & E = *pException->ExceptionRecord; - CONTEXT & C = *pException->ContextRecord; - - // If module with E.ExceptionAddress found - save its path and date. - if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) - { - info["Module"] = ll_convert_wide_to_string(Module_Name); - - if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) - { - if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) - { - FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); - FileTimeToSystemTime(&Local_File_Time, &T); - - info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); - } - CloseHandle(hFile); - } - } - else - { - info["ExceptionAddr"] = (int)E.ExceptionAddress; - } - - info["ExceptionCode"] = (int)E.ExceptionCode; - - /* - //TODO: Fix this - if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - { - // Access violation type - Write/Read. - LLSD exception_info; - exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; - exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); - info["Exception Information"] = exception_info; - } - */ - - - // Save instruction that caused exception. - /* - std::string str; - for (i = 0; i < 16; i++) - str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); - info["Instruction"] = str; - */ - LLSD registers; - registers["EAX"] = (int)C.Eax; - registers["EBX"] = (int)C.Ebx; - registers["ECX"] = (int)C.Ecx; - registers["EDX"] = (int)C.Edx; - registers["ESI"] = (int)C.Esi; - registers["EDI"] = (int)C.Edi; - registers["ESP"] = (int)C.Esp; - registers["EBP"] = (int)C.Ebp; - registers["EIP"] = (int)C.Eip; - registers["EFlags"] = (int)C.EFlags; - info["Registers"] = registers; - } //if (pException) - - // Save call stack info. - Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); - - return info; -} //Get_Exception_Info - -#define UNICODE - - -class LLMemoryReserve { -public: - LLMemoryReserve(); - ~LLMemoryReserve(); - void reserve(); - void release(); -protected: - unsigned char *mReserve; - static const size_t MEMORY_RESERVATION_SIZE; -}; - -LLMemoryReserve::LLMemoryReserve() : - mReserve(NULL) -{ -}; - -LLMemoryReserve::~LLMemoryReserve() -{ - release(); -} - -// I dunno - this just seemed like a pretty good value. -const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024; - -void LLMemoryReserve::reserve() -{ - if(NULL == mReserve) - mReserve = new unsigned char[MEMORY_RESERVATION_SIZE]; -}; - -void LLMemoryReserve::release() -{ - delete [] mReserve; - mReserve = NULL; -}; - -static LLMemoryReserve gEmergencyMemoryReserve; - -#ifndef _M_IX86 - #error "The following code only works for x86!" -#endif -LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( - LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ - if(lpTopLevelExceptionFilter == gFilterFunc) - return gFilterFunc; - - llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl; - LLSD cs_info; - Get_Call_Stack(NULL, NULL, cs_info); - - if(cs_info.has("CallStack") && cs_info["CallStack"].isArray()) - { - LLSD cs = cs_info["CallStack"]; - for(LLSD::array_iterator i = cs.beginArray(); - i != cs.endArray(); - ++i) - { - llinfos << "Module: " << (*i)["ModuleName"] << llendl; - } - } - - return gFilterFunc; -} - -BOOL PreventSetUnhandledExceptionFilter() -{ - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); - if (hKernel32 == NULL) - return FALSE; - - void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); - if(pOrgEntry == NULL) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory(GetCurrentProcess(), - pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); - return bRet; -} - -// static -void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) -{ - return; -#if 0 - static bool s_first_run = true; - // Load the dbghelp dll now, instead of waiting for the crash. - // Less potential for stack mangling - - if (s_first_run) - { - // First, try loading from the directory that the app resides in. - std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); - - HMODULE hDll = NULL; - hDll = LoadLibraryA(local_dll_name.c_str()); - if (!hDll) - { - hDll = LoadLibrary(L"dbghelp.dll"); - } - - if (!hDll) - { - LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; - } - else - { - f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); - - if (!f_mdwp) - { - FreeLibrary(hDll); - hDll = NULL; - } - } - - gEmergencyMemoryReserve.reserve(); - - s_first_run = false; - } - - // Try to get Tool Help library functions. - HMODULE hKernel32; - hKernel32 = GetModuleHandle(_T("KERNEL32")); - CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); - Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); - Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - - PVOID added_filter = - AddVectoredExceptionHandler(0, filter_func); - - if(added_filter == 0) - { - LL_WARNS("AppInit") - << "Failed to add exception handler (" << added_filter << ") !" << LL_ENDL; - } - - gFilterFunc = filter_func; -#endif -} - -bool LLWinDebug::checkExceptionHandler() -{ - bool ok = true; - - RemoveVectoredExceptionHandler(gFilterFunc); - PVOID filter = AddVectoredExceptionHandler(0, gFilterFunc); - - if (filter == NULL) - { - ok = FALSE; - if (gFilterFunc == NULL) - { - LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; - } - else - { - LL_WARNS("AppInit") << "Failed to add exception handler (" << (void *)gFilterFunc << ")!" << LL_ENDL; - } - } - - return ok; -} - -void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename) -{ - if(f_mdwp == NULL || gDirUtilp == NULL) - { - return; - //write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n"); - } - else - { - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - - HANDLE hFile = CreateFileA(dump_path.c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile != INVALID_HANDLE_VALUE) - { - // Write the dump, ignoring the return value - f_mdwp(GetCurrentProcess(), - GetCurrentProcessId(), - hFile, - type, - ExInfop, - NULL, - NULL); - - CloseHandle(hFile); - } - - } -} - -// static -void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - This method is no longer the exception handler. - // Its called from viewer_windows_exception_handler() and other places. - - // - // Let go of a bunch of reserved memory to give library calls etc - // a chance to execute normally in the case that we ran out of - // memory. - // - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SecondLifeException"); - std::string log_path = dump_path + ".log"; - - if (exception_infop) - { - // Since there is exception info... Release the hounds. - gEmergencyMemoryReserve.release(); - - if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - - ExInfo.ThreadId = ::GetCurrentThreadId(); - ExInfo.ExceptionPointers = exception_infop; - ExInfo.ClientPointers = NULL; - - writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp"); - writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); - } - - info = Get_Exception_Info(exception_infop); - } - - LLSD threads; - std::vector thread_ids; - GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); - - for(std::vector::iterator th_itr = thread_ids.begin(); - th_itr != thread_ids.end(); - ++th_itr) - { - LLSD thread_info; - if(*th_itr != GetCurrentThreadId()) - { - GetThreadCallStack(*th_itr, thread_info); - } - - if(thread_info) - { - threads[llformat("ID %d", *th_itr)] = thread_info; - } - } - - info["Threads"] = threads; - - llofstream out_file(log_path); - LLSDSerialize::toPrettyXML(info, out_file); - out_file.close(); -} - -void LLWinDebug::clearCrashStacks() -{ - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException.log"); - LLFile::remove(dump_path); -} diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h deleted file mode 100644 index f4a6a2d54d..0000000000 --- a/indra/newview/llwindebug.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file llwindebug.h - * @brief LLWinDebug class header file - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWINDEBUG_H -#define LL_LLWINDEBUG_H - -#include "stdtypes.h" -#include - -class LLWinDebug -{ -public: - - /** - * @brief initialize the llwindebug exception filter callback - * - * Hand a windows unhandled exception filter to LLWinDebug - * This method should only be called to change the - * exception filter used by llwindebug. - * - * Setting filter_func to NULL will clear any custom filters. - **/ - static void initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func); - - /** - * @brief check the status of the exception filter. - * - * Resets unhandled exception filter to the filter specified - * w/ initExceptionFilter). - * Returns false if the exception filter was modified. - * - * *NOTE:Mani In the past mozlib has been accused of - * overriding the exception filter. If the mozlib filter - * is required, perhaps we can chain calls from our - * filter to mozlib's. - **/ - static bool checkExceptionHandler(); - - static void generateCrashStacks(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); - static void clearCrashStacks(); // Delete the crash stack file(s). - - static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); -private: -}; - -#endif // LL_LLWINDEBUG_H -- cgit v1.2.3 From 637b1e4a3a4fd0e4952795aea851643107d4e965 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 16:24:10 -0700 Subject: fix some dos line endings. --- indra/cmake/GoogleBreakpad.cmake | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake index 0d023b20ec..8270c0fabb 100644 --- a/indra/cmake/GoogleBreakpad.cmake +++ b/indra/cmake/GoogleBreakpad.cmake @@ -1,19 +1,19 @@ -# -*- cmake -*- -include(Prebuilt) - -if (STANDALONE) - MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") - # *TODO - implement this 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 common) - endif (WINDOWS) -endif (STANDALONE) - +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") + # *TODO - implement this 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 common) + endif (WINDOWS) +endif (STANDALONE) + -- cgit v1.2.3 From 8f4c8ebcd55c1ad384303802faaa10e33247914f Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 16:52:12 -0700 Subject: fix darwin build. --- indra/llcommon/llapp.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index e22ff869e7..9e0e8ea814 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -804,6 +804,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) #endif // !WINDOWS +#ifdef LL_DARWIN bool darwin_post_minidump_callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded) @@ -832,7 +833,9 @@ bool darwin_post_minidump_callback(const char *dump_dir, LLApp::runErrorHandler(); return true; } +#endif +#ifdef LL_WINDOWS bool windows_post_minidump_callback(const wchar_t* dump_path, const wchar_t* minidump_id, void* context, @@ -882,3 +885,4 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, return true; } +#endif \ No newline at end of file -- cgit v1.2.3 From 45a86b67518a579b166e1cf6a719d4aed4c35a39 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 24 May 2010 16:53:10 -0700 Subject: fix eof newline --- indra/llcommon/llapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9e0e8ea814..9ea1a18e5f 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -885,4 +885,4 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, return true; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 5a52c5eb8a5cc4e1215911bac9121891dd802d45 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 25 May 2010 13:32:12 -0700 Subject: Mac crash behavior matches windows and linux: report on crash (not after restart). This is OK because we use Breakpad generated minidumps instead of OS generated ones. --- indra/llcommon/llapp.h | 5 +++++ indra/llcrashlogger/llcrashlogger.cpp | 38 +++++++---------------------------- indra/newview/llappviewer.cpp | 26 ++++-------------------- indra/newview/llappviewermacosx.cpp | 32 ----------------------------- 4 files changed, 16 insertions(+), 85 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 725c13866f..8b2dc1ab72 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -235,6 +235,11 @@ public: static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. //@} + + // + // Expose exception handler. + // + google_breakpad::ExceptionHandler * getExceptionHandler(void) { return mExceptionHandler; } #if !LL_WINDOWS // diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 8f5aa5ab2d..9d777cd649 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -155,25 +155,6 @@ std::string getStartupStateFromLog(std::string& sllog) void LLCrashLogger::gatherFiles() { - - /* - //TODO:This function needs to be reimplemented somewhere in here... - if(!previous_crash && is_crash_log) - { - // Make sure the file isn't too old. - double age = difftime(gLaunchTime, stat_data.st_mtimespec.tv_sec); - - // llinfos << "age is " << age << llendl; - - if(age > 60.0) - { - // The file was last modified more than 60 seconds before the crash reporter was launched. Assume it's stale. - llwarns << "File " << mFilename << " is too old!" << llendl; - return; - } - } - */ - updateApplication("Gathering logs..."); // Figure out the filename of the debug log @@ -209,18 +190,12 @@ void LLCrashLogger::gatherFiles() mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); } -#if !LL_DARWIN - if(mCrashInPreviousExec) -#else -#endif - { - // 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; - } + // 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(); @@ -295,6 +270,7 @@ void LLCrashLogger::gatherFiles() mCrashInfo["Minidump"] = data; } } + mCrashInfo["DebugLog"].erase("MinidumpPath"); } LLSD LLCrashLogger::constructPostData() diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e9ec0b8b77..418b587321 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -102,6 +102,8 @@ // Third party library includes #include +#include + #if LL_WINDOWS # include // For _SH_DENYWR in initMarkerFile @@ -2281,17 +2283,7 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS - //*NOTE:Mani The current state of the crash handler has the MacOSX - // sending all crash reports as freezes, in order to let - // the MacOSX CrashRepoter generate stacks before spawning the - // SL crash logger. - // The Linux and Windows clients generate their own stacks and - // spawn the SL crash logger immediately. This may change in the future. -#if LL_DARWIN - if(gLastExecEvent != LAST_EXEC_NORMAL) -#else if (gLastExecEvent == LAST_EXEC_FROZE) -#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2552,9 +2544,6 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Make sure the watchdog gets turned off... -// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what @@ -2665,10 +2654,6 @@ void LLAppViewer::handleViewerCrash() LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2681,8 +2666,6 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); - -#endif //!LL_DARWIN return; } @@ -3287,9 +3270,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; - LLAppViewer::handleSyncViewerCrash(); - LLAppViewer::handleViewerCrash(); - std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3302,6 +3282,8 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); + + LLApp::instance()->getExceptionHandler()->WriteMinidump(); } // This routine may get called more than once during the shutdown process. diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 0b5f18c330..2f12ad7e38 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -384,38 +384,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) } } - - if(!reportFreeze) - { - _exit(1); - } - - // TODO from palmer: Find a better way to handle managing old crash logs - // when this is a separate imbedable module. Ideally just sort crash stack - // logs based on date, and grab the latest one as opposed to deleting them - // for thoughts on what the module would look like. - // See: https://wiki.lindenlab.com/wiki/Viewer_Crash_Reporter_Round_4 - - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // The old crash stack is invalid for the next crash report. - char path[MAX_PATH]; - FSRef folder; - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - std::string pathname = std::string(path) + std::string("/CrashReporter/"); - std::string mask = "Second Life*"; - std::string file_name; - while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) - { - LLFile::remove(pathname + file_name); - } - } - } - } std::string LLAppViewerMacOSX::generateSerialNumber() -- cgit v1.2.3 From 6a39149fec72e3a105d7a47b8a9f5aa2a0bfba87 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 25 May 2010 15:08:36 -0700 Subject: Added configuration setting to send crash reports to configured url rather than through the grid. --- indra/llcrashlogger/llcrashlogger.cpp | 7 ++++++- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llappviewer.cpp | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 9d777cd649..2ec7347db0 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -200,7 +200,12 @@ void LLCrashLogger::gatherFiles() gatherPlatformSpecificFiles(); //Use the debug log to reconstruct the URL to send the crash report to - if(mDebugLog.has("CurrentSimHost")) + if(mDebugLog.has("CrashHostUrl")) + { + // Crash log receiver has been manually configured. + mCrashHost = mDebugLog["CrashHostUrl"].asString(); + } + else if(mDebugLog.has("CurrentSimHost")) { mCrashHost = "https://"; mCrashHost += mDebugLog["CurrentSimHost"].asString(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f71662a7c8..6dcbb4e57a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,6 +1,17 @@ + CrashHostUrl + + Comment + A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler. + Persist + 1 + Type + String + Value + + AFKTimeout Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 418b587321..7cdd8ca309 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2545,6 +2545,13 @@ void LLAppViewer::handleViewerCrash() } pApp->mReportedCrash = TRUE; + // Insert crash host url (url to post crash log to) if configured. + std::string crashHostUrl = gSavedSettings.get("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } + //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what gDebugInfo["ClientInfo"]["Name"] = gSavedSettings.getString("VersionChannelName"); -- cgit v1.2.3 From a63b6dd93c1ef78e647dbd221a5a3b14ff363102 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Wed, 26 May 2010 14:43:27 +0100 Subject: Hooked up Google Breakpad for the Linux client too. Using Alain's Darwin reporter callback was all that was needed. Also replaced the call that exposed the breakpad exception class with a call to just write out the minidump, as that was the only reason for exposing it. Now clients don't need to know about Google Breakpad. --- indra/llcommon/llapp.cpp | 32 ++++++++++---------------------- indra/llcommon/llapp.h | 4 ++-- indra/newview/llappviewer.cpp | 8 +++++--- 3 files changed, 17 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9ea1a18e5f..6f4acd49b1 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -68,7 +68,7 @@ void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); // Called by breakpad exception handler after the minidump has been generated. -bool darwin_post_minidump_callback(const char *dump_dir, +bool unix_post_minidump_callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded); # if LL_DARWIN @@ -282,19 +282,11 @@ void LLApp::setupErrorHandling() // occasionally checks to see if the app is in an error state, and sees if it needs to be run. #if LL_WINDOWS - // Windows doesn't have the same signal handling mechanisms as UNIX, thus APR doesn't provide - // a signal handling thread implementation. - // What we do is install an unhandled exception handler, which will try to do the right thing - // in the case of an error (generate a minidump) - - // Disable this until the viewer gets ported so server crashes can be JIT debugged. - //LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - //prev_filter = SetUnhandledExceptionFilter(default_windows_exception_handler); - // 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) { llwarns << "adding breakpad exception handler" << llendl; @@ -309,18 +301,14 @@ void LLApp::setupErrorHandling() // 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(); - -#ifdef LL_DARWIN - // Add google breakpad exception handler configured for Darwin. + // Add google breakpad exception handler configured for Darwin/Linux. if(mExceptionHandler == 0) { std::string dumpPath = "/tmp/"; - mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &darwin_post_minidump_callback, 0, true); + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); } -#endif #endif startErrorThread(); @@ -373,7 +361,6 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } - // static void LLApp::setStatus(EAppStatus status) { @@ -393,6 +380,10 @@ void LLApp::setError() } } +void LLApp::writeMiniDump() +{ + mExceptionHandler->WriteMinidump(); +} // static void LLApp::setQuitting() @@ -802,10 +793,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } -#endif // !WINDOWS - -#ifdef LL_DARWIN -bool darwin_post_minidump_callback(const char *dump_dir, +bool unix_post_minidump_callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded) { @@ -833,7 +821,7 @@ bool darwin_post_minidump_callback(const char *dump_dir, LLApp::runErrorHandler(); return true; } -#endif +#endif // !WINDOWS #ifdef LL_WINDOWS bool windows_post_minidump_callback(const wchar_t* dump_path, diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 8b2dc1ab72..7b1144ebf1 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -237,9 +237,9 @@ public: //@} // - // Expose exception handler. + // Write out a Google Breakpad minidump file. // - google_breakpad::ExceptionHandler * getExceptionHandler(void) { return mExceptionHandler; } + void writeMiniDump(); #if !LL_WINDOWS // diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 7cdd8ca309..0484659793 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -102,7 +102,6 @@ // Third party library includes #include -#include #if LL_WINDOWS @@ -2582,7 +2581,10 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); - if(pApp->minidump_path[0] != 0) gDebugInfo["MinidumpPath"] = pApp->minidump_path; + if(pApp->minidump_path[0] != 0) + { + gDebugInfo["MinidumpPath"] = pApp->minidump_path; + } if(gLogoutInProgress) { @@ -3290,7 +3292,7 @@ void LLAppViewer::badNetworkHandler() "www.secondlife.com/support"; forceDisconnect(message.str()); - LLApp::instance()->getExceptionHandler()->WriteMinidump(); + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. -- cgit v1.2.3 From 0bf02ad820abdb35b9cfdfbd1635953e63a767b2 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 May 2010 12:21:55 -0400 Subject: VPLAT-268: Update Mac for relative-path libexception_handler.dylib Also add the dylib to Copy3rdPartyLibs.cmake so unit tests can find it. --- indra/cmake/Copy3rdPartyLibs.cmake | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 937d3c6384..89422fbdb2 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -167,6 +167,7 @@ elseif(DARWIN) libexpat.dylib libllqtwebkit.dylib libndofdev.dylib + libexception_handler.dylib ) # fmod is statically linked on darwin -- cgit v1.2.3 From 4dec1430202d1c5578c4e0a6d4107c88f1050ab3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 26 May 2010 16:07:16 -0400 Subject: VPLAT-268: Add libexception_handler.dylib to viewer_manifest.py. Without this, the viewer fails to start because it can't find the new libexception_handler.dylib. --- indra/newview/viewer_manifest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 96541088b5..cf66fbc383 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -636,7 +636,9 @@ class DarwinManifest(ViewerManifest): if dylibs["llcommon"]: for libfile in ("libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): self.path(os.path.join(libdir, libfile), libfile) #libfmodwrapper.dylib -- cgit v1.2.3 From 05761d785335f08dc176aa6ebb7f0cd45d1298ab Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Thu, 27 May 2010 15:04:06 +0100 Subject: Removed the SyncErrorHandler from llapp and llappviewer*. This was only used for the Linux client to dump a stack trace to stack_trace.log, which is no longer needed now that we are using Google Breakpad. I also removed all of the stack printing code from llappviewerlinux.cpp. --- indra/llcommon/llapp.cpp | 25 +--- indra/llcommon/llapp.h | 3 - indra/newview/llappviewer.cpp | 7 -- indra/newview/llappviewer.h | 2 - indra/newview/llappviewerlinux.cpp | 224 ------------------------------------ indra/newview/llappviewerlinux.h | 1 - indra/newview/llappviewermacosx.cpp | 5 - indra/newview/llappviewermacosx.h | 1 - indra/newview/llappviewerwin32.cpp | 5 - indra/newview/llappviewerwin32.h | 1 - 10 files changed, 2 insertions(+), 272 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6f4acd49b1..da14020f2b 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -96,7 +96,6 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status LLAppErrorHandler LLApp::sErrorHandler = NULL; -LLAppErrorHandler LLApp::sSyncErrorHandler = NULL; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -334,21 +333,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler) LLApp::sErrorHandler = handler; } - -void LLApp::setSyncErrorHandler(LLAppErrorHandler handler) -{ - LLApp::sSyncErrorHandler = handler; -} - -// static -void LLApp::runSyncErrorHandler() -{ - if (LLApp::sSyncErrorHandler) - { - LLApp::sSyncErrorHandler(); - } -} - // static void LLApp::runErrorHandler() { @@ -371,13 +355,8 @@ void LLApp::setStatus(EAppStatus status) // static void LLApp::setError() { - if (!isError()) - { - // perform any needed synchronous error-handling - runSyncErrorHandler(); - // set app status to ERROR so that the LLErrorThread notices - setStatus(APP_STATUS_ERROR); - } + // set app status to ERROR so that the LLErrorThread notices + setStatus(APP_STATUS_ERROR); } void LLApp::writeMiniDump() diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 7b1144ebf1..a6294a5e1a 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -231,9 +231,7 @@ public: void setupErrorHandling(); void setErrorHandler(LLAppErrorHandler handler); - void setSyncErrorHandler(LLAppErrorHandler handler); static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. - static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. //@} // @@ -306,7 +304,6 @@ private: // their own purposes typedef int(*signal_handler_func)(int signum); static LLAppErrorHandler sErrorHandler; - static LLAppErrorHandler sSyncErrorHandler; // Default application threads LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0484659793..1ad180a024 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2513,13 +2513,6 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } -void LLAppViewer::handleSyncViewerCrash() -{ - LLAppViewer* pApp = LLAppViewer::instance(); - // Call to pure virtual, handled by platform specific llappviewer instance. - pApp->handleSyncCrashTrace(); -} - void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 5acd6e11c4..0b862a92a1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -92,9 +92,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 handleCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? - virtual void handleSyncCrashTrace() = 0; // any low-level crash-prep that has to happen in the context of the crashing thread before the crash report is delivered. static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. - static void handleSyncViewerCrash(); // Hey! The viewer crashed. Do this right NOW in the context of the crashing thread. void checkForCrash(); // Thread accessors diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 78b0f7ba83..ba9a4e4a6e 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -46,23 +46,6 @@ #include -#if LL_LINUX -# include // RTLD_LAZY -# include // backtrace - glibc only -#elif LL_SOLARIS -# include -# include -# include -# include -#endif - -#ifdef LL_ELFBIN -# ifdef __GNUC__ -# include // for symbol demangling -# endif -# include "ELFIO/ELFIO.h" // for better backtraces -#endif - #if LL_DBUS_ENABLED # include "llappviewerlinux_api_dbus.h" @@ -86,7 +69,6 @@ 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. - LLAppViewer::handleSyncViewerCrash(); LLAppViewer::handleViewerCrash(); // we've probably been killed-off before now, but... gOldTerminateHandler(); // call old terminate() handler @@ -109,7 +91,6 @@ int main( int argc, char **argv ) gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); // install crash handlers viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - viewer_app_ptr->setSyncErrorHandler(LLAppViewer::handleSyncViewerCrash); bool ok = viewer_app_ptr->init(); if(!ok) @@ -138,201 +119,6 @@ int main( int argc, char **argv ) return 0; } -#ifdef LL_SOLARIS -static inline BOOL do_basic_glibc_backtrace() -{ - BOOL success = FALSE; - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - printstack(fileno(StraceFile)); - - if (StraceFile != stderr) - fclose(StraceFile); - - return success; -} -#else -#define MAX_STACK_TRACE_DEPTH 40 -// This uses glibc's basic built-in stack-trace functions for a not very -// amazing backtrace. -static inline BOOL do_basic_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t size; - char **strings; - size_t i; - BOOL success = FALSE; - - size = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, size); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - if (size) - { - for (i = 0; i < size; i++) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3lu ", (unsigned long)i); - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[i]); - fprintf(StraceFile, "%s\n", strings[i]); - } - - success = TRUE; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - free (strings); - return success; -} - -#if LL_ELFBIN -// This uses glibc's basic built-in stack-trace functions together with -// ELFIO's ability to parse the .symtab ELF section for better symbol -// extraction without exporting symbols (which'd cause subtle, fatal bugs). -static inline BOOL do_elfio_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t btsize; - char **strings; - BOOL success = FALSE; - - std::string appfilename = gDirUtilp->getExecutablePathAndName(); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - // get backtrace address list and basic symbol info - btsize = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, btsize); - - // create ELF reader for our app binary - IELFI* pReader; - const IELFISection* pSec = NULL; - IELFISymbolTable* pSymTbl = 0; - if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) || - ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) || - // find symbol table, create reader-object - NULL == (pSec = pReader->GetSection( ".symtab" )) || - ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) ) - { - // Failed to open our binary and read its symbol table somehow - llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl; - if (StraceFile != stderr) - fclose(StraceFile); - // note that we may be leaking some of the above ELFIO - // objects now, but it's expected that we'll be dead soon - // and we want to tread delicately until we get *some* kind - // of useful backtrace. - return do_basic_glibc_backtrace(); - } - - // iterate over trace and symtab, looking for plausible symbols - std::string name; - Elf32_Addr value; - Elf32_Word ssize; - unsigned char bind; - unsigned char type; - Elf32_Half section; - int nSymNo = pSymTbl->GetSymbolNum(); - size_t btpos; - for (btpos = 0; btpos < btsize; ++btpos) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3ld ", (long)btpos); - int symidx; - for (symidx = 0; symidx < nSymNo; ++symidx) - { - if (ERR_ELFIO_NO_ERROR == - pSymTbl->GetSymbol(symidx, name, value, ssize, - bind, type, section)) - { - // check if trace address within symbol range - if (uintptr_t(stackarray[btpos]) >= value && - uintptr_t(stackarray[btpos]) < value+ssize) - { - // symbol is inside viewer - fprintf(StraceFile, "%-32s\t", "com.secondlife.indra.viewer"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - - char *demangled_str = NULL; - int demangle_result = 1; - demangled_str = - abi::__cxa_demangle - (name.c_str(), NULL, NULL, - &demangle_result); - if (0 == demangle_result && - NULL != demangled_str) { - fprintf(StraceFile, - "%s", demangled_str); - free(demangled_str); - } - else // failed demangle; print it raw - { - fprintf(StraceFile, - "%s", name.c_str()); - } - // print offset from symbol start - fprintf(StraceFile, - " + %lu\n", - uintptr_t(stackarray[btpos]) - - value); - goto got_sym; // early escape - } - } - } - // Fallback: - // Didn't find a suitable symbol in the binary - it's probably - // a symbol in a DSO; use glibc's idea of what it should be. - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - fprintf(StraceFile, "%s\n", strings[btpos]); - got_sym:; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - pSymTbl->Release(); - pSec->Release(); - pReader->Release(); - - free(strings); - - llinfos << "Finished generating stack trace." << llendl; - - success = TRUE; - return success; -} -#endif // LL_ELFBIN - -#endif // LL_SOLARIS - - LLAppViewerLinux::LLAppViewerLinux() { } @@ -541,16 +327,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) } #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::handleSyncCrashTrace() -{ - // This backtrace writes into stack_trace.log -# if LL_ELFBIN - do_elfio_glibc_backtrace(); // more useful backtrace -# else - do_basic_glibc_backtrace(); // only slightly useful backtrace -# endif // LL_ELFBIN -} - void LLAppViewerLinux::handleCrashReporting(bool reportFreeze) { std::string cmd =gDirUtilp->getExecutableDir(); diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 230c0dc24b..b17380d4d8 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -68,7 +68,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool initLogging(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 2f12ad7e38..1e66e55f3d 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -264,11 +264,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -void LLAppViewerMacOSX::handleSyncCrashTrace() -{ - // do nothing -} - static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData) diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index cbf7e6c209..3d7bb55556 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -55,7 +55,6 @@ public: protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); std::string generateSerialNumber(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 88d8dba8af..e3ef04d03d 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -479,11 +479,6 @@ bool LLAppViewerWin32::restoreErrorTrap() //return LLWinDebug::checkExceptionHandler(); } -void LLAppViewerWin32::handleSyncCrashTrace() -{ - // do nothing -} - void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) { const char* logger_name = "win_crash_logger.exe"; diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 13454edeec..52dcc583a4 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -57,7 +57,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool sendURLToOtherInstance(const std::string& url); -- cgit v1.2.3 From bd32a9c6efc5598711bfed9ff20d049878bc96a4 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Thu, 27 May 2010 15:47:05 +0100 Subject: Don't try to add old stack trace files to the crash report. Such as stack_trace.log on Linux or SecondLifeException.log on Win32. --- indra/linux_crash_logger/llcrashloggerlinux.cpp | 1 - indra/llcrashlogger/llcrashlogger.cpp | 1 - indra/newview/llappviewerlinux.cpp | 2 ++ indra/win_crash_logger/llcrashloggerwindows.cpp | 1 - 4 files changed, 2 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index 039b70ec4a..ce03ea0d6f 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -120,7 +120,6 @@ LLCrashLoggerLinux::~LLCrashLoggerLinux(void) void LLCrashLoggerLinux::gatherPlatformSpecificFiles() { - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log").c_str(); } bool LLCrashLoggerLinux::mainLoop() diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 2ec7347db0..aa2ea17af9 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -227,7 +227,6 @@ void LLCrashLogger::gatherFiles() mCrashInfo["DebugLog"] = mDebugLog; mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); - mFileMap["StackTrace"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); updateApplication("Encoding files..."); diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index ba9a4e4a6e..78afdc8995 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -462,6 +462,8 @@ bool LLAppViewerLinux::beingDebugged() bool LLAppViewerLinux::initLogging() { // Remove the last stack trace, if any + // This file is no longer created, since the move to Google Breakpad + // The code is left here to clean out any old state in the log dir std::string old_stack_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); LLFile::remove(old_stack_file); diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index c9e01c8418..2884231299 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -299,7 +299,6 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles() // At this point we're responsive enough the user could click the close button SetCursor(gCursorArrow); mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLifeException.log"); } bool LLCrashLoggerWindows::mainLoop() -- cgit v1.2.3 From 2cfa661c279b4c74b33a86bba600d02df5d2706c Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 27 May 2010 14:49:15 -0700 Subject: WIP VPLAT-248 - added a generate_breakpad_symbols target to the build and info to upload symbol files to s3 after the build. --- indra/newview/CMakeLists.txt | 36 ++++++++++++++ indra/newview/generate_breakpad_symbols.py | 78 ++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 indra/newview/generate_breakpad_symbols.py (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4571aa1074..a0340a1e23 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1776,6 +1776,42 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) +if (PACKAGE) + if (WINDOWS) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + set(VIEWER_SYMBOL_FILE "secondlife-windows.breakpad.bz2") + set(VIEWER_EXE_GLOBS "SecondLife*.exe SLPlugin.exe") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + endif (WINDOWS) + if (DARWIN) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") + set(VIEWER_SYMBOL_FILE "secondlife-darwin.breakpad.bz2") + set(VIEWER_EXE_GLOBS "Second?Life SLPlugin") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + endif (DARWIN) + if (LINUX) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") + set(VIEWER_SYMBOL_FILE "secondlife-linux.breakpad.bz2") + set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") + endif (LINUX) + + add_custom_command(OUTPUT "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${VIEWER_DIST_DIR}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" + "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py + ) + add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols viewer) + add_dependencies(package generate_breakpad_symbols) +endif (PACKAGE) + if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below # This creates a separate test project per file listed. diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py new file mode 100644 index 0000000000..884dd06f84 --- /dev/null +++ b/indra/newview/generate_breakpad_symbols.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# @file generate_breakpad_symbols.py +# @author Brad Kittenbrink +# @brief Simple tool for generating google_breakpad symbol information +# for the crash reporter. +# +# $LicenseInfo:firstyear=2010&license=viewergpl$ +# +# Copyright (c) 2010-2010, Linden Research, Inc. +# +# Second Life Viewer Source Code +# The source code in this file ("Source Code") is provided by Linden Lab +# to you under the terms of the GNU General Public License, version 2.0 +# ("GPL"), unless you have obtained a separate licensing agreement +# ("Other License"), formally executed by you and Linden Lab. Terms of +# the GPL can be found in doc/GPL-license.txt in this distribution, or +# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +# +# There are special exceptions to the terms and conditions of the GPL as +# it is applied to this Source Code. View the full text of the exception +# in the file doc/FLOSS-exception.txt in this software distribution, or +# online at +# http://secondlifegrid.net/programs/open_source/licensing/flossexception +# +# By copying, modifying or distributing this software, you acknowledge +# that you have read and understood your obligations described above, +# and agree to abide by those obligations. +# +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + + +import collections +import fnmatch +import itertools +import os +import sys +import subprocess +import bz2 + +def usage(): + print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] + +def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): + print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + + def matches(f): + return f in viewer_exes or fnmatch.fnmatch(f, libs_suffix) + + def list_files(): + for (dirname, subdirs, filenames) in os.walk(viewer_dir): + #print "scanning '%s' for modules..." % dirname + for f in itertools.ifilter(matches, filenames): + yield os.path.join(dirname, f) + + def dump_module(m): + print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) + child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) + out, err = child.communicate() + return out + + out = bz2.BZ2File(viewer_symbol_file, 'w') + + for symbols in map(dump_module, list_files()): + out.writelines(symbols) + + out.close() + + return 0 + +if __name__ == "__main__": + if len(sys.argv) != 6: + usage() + sys.exit(1) + sys.exit(main(*sys.argv[1:])) + -- cgit v1.2.3 From 4e8d423cc5fae86c8273df5e7ea583a9e0475711 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 27 May 2010 15:29:18 -0700 Subject: WIP VPLAT-248 - Bugfix for last checkin (build depencencies for new generate_breakpad_symbols target were slightly off) thanks for the code review mani! --- indra/newview/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index a0340a1e23..78691439ee 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1807,7 +1807,7 @@ if (PACKAGE) "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}" DEPENDS generate_breakpad_symbols.py ) - add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") + add_custom_target(generate_breakpad_symbols ALL DEPENDS "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}") add_dependencies(generate_breakpad_symbols viewer) add_dependencies(package generate_breakpad_symbols) endif (PACKAGE) -- cgit v1.2.3 From d1c42b2bf384f0352c775ba0e765d000c405ea36 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 27 May 2010 19:12:29 -0700 Subject: Fix for linux build breakage. --- indra/newview/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 28c00f9984..5746bc27f9 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1781,24 +1781,24 @@ endif (INSTALL) if (PACKAGE) if (WINDOWS) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "secondlife-windows.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-windows.breakpad.bz2") set(VIEWER_EXE_GLOBS "SecondLife*.exe SLPlugin.exe") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") endif (WINDOWS) if (DARWIN) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") - set(VIEWER_SYMBOL_FILE "secondlife-darwin.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-darwin.breakpad.bz2") set(VIEWER_EXE_GLOBS "Second?Life SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") endif (DARWIN) if (LINUX) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") - set(VIEWER_SYMBOL_FILE "secondlife-linux.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-linux.breakpad.bz2") set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") endif (LINUX) - add_custom_command(OUTPUT "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}" + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" COMMAND "${PYTHON_EXECUTABLE}" ARGS "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" @@ -1806,10 +1806,10 @@ if (PACKAGE) "${VIEWER_EXE_GLOBS}" "${VIEWER_LIB_GLOB}" "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" - "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}" + "${VIEWER_SYMBOL_FILE}" DEPENDS generate_breakpad_symbols.py ) - add_custom_target(generate_breakpad_symbols ALL DEPENDS "${CMAKE_CFG_INTDIR}/${VIEWER_SYMBOL_FILE}") + add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") add_dependencies(generate_breakpad_symbols viewer) add_dependencies(package generate_breakpad_symbols) endif (PACKAGE) -- cgit v1.2.3 From 3729983908d365843bf8cf85178b61f719448374 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 27 May 2010 19:13:51 -0700 Subject: WIP VPLAT-248 cleanups for google_breakpad symbol file generation. --- indra/newview/CMakeLists.txt | 4 ++-- indra/newview/generate_breakpad_symbols.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5746bc27f9..d5c90b6f2a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1782,13 +1782,13 @@ if (PACKAGE) if (WINDOWS) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-windows.breakpad.bz2") - set(VIEWER_EXE_GLOBS "SecondLife*.exe SLPlugin.exe") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME} SLPlugin.exe") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") endif (WINDOWS) if (DARWIN) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-darwin.breakpad.bz2") - set(VIEWER_EXE_GLOBS "Second?Life SLPlugin") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME} SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") endif (DARWIN) if (LINUX) diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index 884dd06f84..f281846918 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -44,7 +44,7 @@ def usage(): print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): - print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + # print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) def matches(f): return f in viewer_exes or fnmatch.fnmatch(f, libs_suffix) -- cgit v1.2.3 From 4fb77380279bdf853b7f213ba8997511720468dd Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Fri, 28 May 2010 15:10:52 +0100 Subject: Write breakpad minidump files to the SL log directory. Also, clean out old minidump files when we start up. --- indra/llcommon/llapp.cpp | 38 ++++++++++++++++++++++++++++++-------- indra/llcommon/llapp.h | 16 +++++++++++----- indra/newview/llappviewer.cpp | 13 +++++++++++-- 3 files changed, 52 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index da14020f2b..861122a4ac 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -140,6 +140,8 @@ void LLApp::commonCtor() mExceptionHandler = 0; + // initialize the buffer to write the minidump filename to + // (this is used to avoid allocating memory in the crash handler) memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH); } @@ -359,8 +361,15 @@ void LLApp::setError() setStatus(APP_STATUS_ERROR); } +void LLApp::setMiniDumpDir(const std::string &path) +{ + llassert(mExceptionHandler); + mExceptionHandler->set_dump_path(path); +} + void LLApp::writeMiniDump() { + llassert(mExceptionHandler); mExceptionHandler->WriteMinidump(); } @@ -786,17 +795,25 @@ bool unix_post_minidump_callback(const char *dump_dir, // The path must not be truncated. llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); - char * path = LLApp::instance()->minidump_path; + char * path = LLApp::instance()->getMiniDumpFilename(); S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; strncpy(path, dump_dir, remaining); remaining -= dirPathLength; path += dirPathLength; - strncpy(path, minidump_id, remaining); - remaining -= idLength; - path += idLength; - strncpy(path, ".dmp", remaining); + 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); + } - llinfos << "generated minidump: " << LLApp::instance()->minidump_path << llendl; + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; LLApp::runErrorHandler(); return true; } @@ -810,13 +827,18 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, MDRawAssertionInfo* assertion, bool succeeded) { - char * path = LLApp::instance()->minidump_path; + char * path = LLApp::instance()->getMiniDumpFilename(); S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; size_t bytesUsed; bytesUsed = wcstombs(path, dump_path, static_cast(remaining)); remaining -= bytesUsed; path += bytesUsed; + if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') + { + *path++ = '\\'; + --remaining; + } if(remaining > 0) { bytesUsed = wcstombs(path, minidump_id, static_cast(remaining)); @@ -828,7 +850,7 @@ bool windows_post_minidump_callback(const wchar_t* dump_path, strncpy(path, ".dmp", remaining); } - llinfos << "generated minidump: " << LLApp::instance()->minidump_path << llendl; + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; // *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 diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index a6294a5e1a..fef05a7939 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -234,9 +234,16 @@ 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); + + // Return the Google Breakpad minidump filename after a crash. + char *getMiniDumpFilename() { return minidump_path; } + // Write out a Google Breakpad minidump file. - // void writeMiniDump(); #if !LL_WINDOWS @@ -274,9 +281,6 @@ public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map - // Contains the path to minidump file after a crash. - static const U32 MAX_MINDUMP_PATH_LENGTH = 256; - char minidump_path[MAX_MINDUMP_PATH_LENGTH]; protected: static void setStatus(EAppStatus status); // Use this to change the application status. @@ -298,6 +302,8 @@ protected: private: void startErrorThread(); + // Contains the filename of the minidump file after a crash. + char minidump_path[MAX_MINDUMP_PATH_LENGTH]; // *NOTE: On Windows, we need a routine to reset the structured // exception handler when some evil driver has taken it over for diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 00a2678a9a..3528deb9e0 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -602,6 +602,14 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; + // write Google Breakpad minidump files to our log directory + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + setMiniDumpDir(logdir); + + // remove any old minidump files from the log directory + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + // Although initLogging() is the right place to mess with // setFatalFunction(), we can't query gSavedSettings until after // initConfiguration(). @@ -2574,9 +2582,10 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); - if(pApp->minidump_path[0] != 0) + char *minidump_file = pApp->getMiniDumpFilename(); + if(minidump_file && minidump_file[0] != 0) { - gDebugInfo["MinidumpPath"] = pApp->minidump_path; + gDebugInfo["MinidumpPath"] = minidump_file; } if(gLogoutInProgress) -- cgit v1.2.3 From 590a3d891c138f881d7a3f7c2758e778256e3891 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Fri, 28 May 2010 15:40:16 +0100 Subject: On Windows, you have to pass the minidump path as a wstring. --- indra/llcommon/llapp.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 861122a4ac..1ea888f2e0 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -43,6 +43,7 @@ #include "lllivefile.h" #include "llmemory.h" #include "llstl.h" // for DeletePointer() +#include "llstring.h" #include "lleventtimer.h" #include "google_breakpad/exception_handler.h" @@ -364,7 +365,11 @@ void LLApp::setError() void LLApp::setMiniDumpDir(const std::string &path) { llassert(mExceptionHandler); +#ifdef LL_WINDOWS + mExceptionHandler->set_dump_path(utf8str_to_wstring(path)); +#else mExceptionHandler->set_dump_path(path); +#endif } void LLApp::writeMiniDump() -- cgit v1.2.3 From 80d9cde59656964335613f99dfa63bb834278416 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Fri, 28 May 2010 16:15:00 +0100 Subject: Try using mbstowcs() to convert to std::wstring. LLWString cannot be converted to std::wstring, apparently. --- indra/llcommon/llapp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 1ea888f2e0..eedec0b24e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -366,7 +366,9 @@ void LLApp::setMiniDumpDir(const std::string &path) { llassert(mExceptionHandler); #ifdef LL_WINDOWS - mExceptionHandler->set_dump_path(utf8str_to_wstring(path)); + wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; + mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH); + mExceptionHandler->set_dump_path(std::wstring(buffer)); #else mExceptionHandler->set_dump_path(path); #endif -- cgit v1.2.3 From d71ea5ffd94ed1dc1b6ad6f4b57fc2e11dfc7a23 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Fri, 28 May 2010 22:14:06 +0100 Subject: Remove old minidump files on a clean exit, not on startup. --- indra/newview/llappviewer.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3528deb9e0..5f2e16ef12 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -607,9 +607,6 @@ bool LLAppViewer::init() logdir += gDirUtilp->getDirDelimiter(); setMiniDumpDir(logdir); - // remove any old minidump files from the log directory - gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); - // Although initLogging() is the right place to mess with // setFatalFunction(), we can't query gSavedSettings until after // initConfiguration(). @@ -1234,6 +1231,14 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); + // remove any old breakpad minidump files from the log directory + if (! isError()) + { + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + } + // *TODO - generalize this and move DSO wrangling to a helper class -brad std::set::const_iterator i; for(i = mPlugins.begin(); i != mPlugins.end(); ++i) -- cgit v1.2.3 From 3a6d903ce02c4d1b06b829ef88bd826e90fd74d0 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 28 May 2010 14:51:12 -0700 Subject: mac llcommon dependent apps like mac-crash-logger get libexception_handler correctly packaged. --- indra/newview/viewer_manifest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index cf66fbc383..dac1409aee 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -659,7 +659,9 @@ class DarwinManifest(ViewerManifest): for libfile in ("libllcommon.dylib", "libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): target_lib = os.path.join('../../..', libfile) self.run_command("ln -sf %(target)r %(link)r" % {'target': target_lib, -- cgit v1.2.3 From f24335d7901b040365b4934c5fc0ce8f7d694f18 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 1 Jun 2010 14:07:20 -0700 Subject: Fix log file inclusion; include SecondLife.log on crash, but SecondLife.old on freeze. --- indra/llcrashlogger/llcrashlogger.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index aa2ea17af9..078795f962 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -190,12 +190,16 @@ void LLCrashLogger::gatherFiles() mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); } - // 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; + 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(); -- cgit v1.2.3 From bca81fdc7e4257169ecb337e299573a2c1e24619 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 1 Jun 2010 14:20:47 -0700 Subject: remove uneeded search for macos crash reports; superceded by Breakpad minidumps. --- indra/mac_crash_logger/llcrashloggermac.cpp | 83 ----------------------------- 1 file changed, 83 deletions(-) (limited to 'indra') diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 16efa4fe2c..90de39ba27 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -211,89 +211,6 @@ bool LLCrashLoggerMac::init(void) void LLCrashLoggerMac::gatherPlatformSpecificFiles() { updateApplication("Gathering hardware information..."); - char path[MAX_PATH]; - FSRef folder; - - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - struct stat dw_stat; - std::string mBuf; - bool isLeopard = false; - // Try the 10.3 path first... - std::string dw_file_name = std::string(path) + std::string("/CrashReporter/Second Life.crash.log"); - int res = stat(dw_file_name.c_str(), &dw_stat); - - if (res) - { - // Try the 10.2 one next... - dw_file_name = std::string(path) + std::string("/Second Life.crash.log"); - res = stat(dw_file_name.c_str(), &dw_stat); - } - - if(res) - { - //10.5: Like 10.3+, except it puts the crash time in the file instead of dividing it up - //using asterisks. Get a directory listing, search for files starting with second life, - //use the last one found. - std::string old_file_name, current_file_name, pathname, mask; - pathname = std::string(path) + std::string("/CrashReporter/"); - mask = "Second Life*"; - while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false)) - { - old_file_name = current_file_name; - } - if(old_file_name != "") - { - dw_file_name = pathname + old_file_name; - res=stat(dw_file_name.c_str(), &dw_stat); - isLeopard = true; - } - } - - if (!res) - { - std::ifstream fp(dw_file_name.c_str()); - std::stringstream str; - if(!fp.is_open()) return; - str << fp.rdbuf(); - mBuf = str.str(); - - if(!isLeopard) - { - // Crash logs consist of a number of entries, one per crash. - // Each entry is preceeded by "**********" on a line by itself. - // We want only the most recent (i.e. last) one. - const char *sep = "**********"; - const char *start = mBuf.c_str(); - const char *cur = start; - const char *temp = strstr(cur, sep); - - while(temp != NULL) - { - // Skip past the marker we just found - cur = temp + strlen(sep); /* Flawfinder: ignore */ - - // and try to find another - temp = strstr(cur, sep); - } - - // If there's more than one entry in the log file, strip all but the last one. - if(cur != start) - { - mBuf.erase(0, cur - start); - } - } - mCrashInfo["CrashLog"] = mBuf; - } - else - { - llwarns << "Couldn't find any CrashReporter files..." << llendl; - } - } - } } bool LLCrashLoggerMac::mainLoop() -- cgit v1.2.3 From 1a460b0f086319cf3db2297338afc5cf557b7fae Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 1 Jun 2010 19:05:07 -0700 Subject: Finished VPLAT-248: Fix for symbol file generation missing info. Actually this is kind of 3 independent fixes, one for a different bug on each platform. --- indra/newview/CMakeLists.txt | 33 +++++++++++++++++++++++++++++---- indra/newview/viewer_manifest.py | 3 ++- 2 files changed, 31 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b145fbee1f..3a599b59fd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1695,6 +1695,28 @@ if (LINUX) add_dependencies(package linux-updater-target) check_message_template(package) endif (NOT INSTALL) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --arch=${ARCH} + --actions=copy + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} + --configuration=${CMAKE_CFG_INTDIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged + --grid=${GRID} + --source=${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${COPY_INPUT_DEPENDENCIES} + COMMENT "Performing viewer_manifest copy" + ) + + add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) endif (LINUX) if (DARWIN) @@ -1786,20 +1808,22 @@ if (PACKAGE) if (WINDOWS) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-windows.breakpad.bz2") - set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME} SLPlugin.exe") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) endif (WINDOWS) if (DARWIN) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-darwin.breakpad.bz2") - set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME} SLPlugin") - set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") + set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-linux.breakpad.bz2") set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") + set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) endif (LINUX) add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" @@ -1812,9 +1836,10 @@ if (PACKAGE) "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" "${VIEWER_SYMBOL_FILE}" DEPENDS generate_breakpad_symbols.py + VERBATIM ) add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols viewer) + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") add_dependencies(package generate_breakpad_symbols) endif (PACKAGE) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index dac1409aee..255995aea9 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -930,7 +930,8 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - if self.args['buildtype'].lower() == 'release': + # *TODO switch this to use self.is_packaging_viewer() once I understand all the consequences -brad + if self.args['buildtype'].lower() == 'release' and 'package' in self.args['actions']: print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure -- cgit v1.2.3 From dfce986b8b85a8497fe4267d251b18dff7c17ef3 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 1 Jun 2010 23:20:52 -0700 Subject: Fix for dependencies in the linux build symbol generation. --- indra/newview/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3a599b59fd..64e2b40380 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1717,6 +1717,7 @@ if (LINUX) ) add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) + add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}") endif (LINUX) if (DARWIN) -- cgit v1.2.3 From 8990498b420ba7083aa35c3eb08d87ebcd2a29a4 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 2 Jun 2010 11:03:03 -0700 Subject: Crash logger renames log flies to safe names so they don't get clobbered on SL restart. Old logs are cleaned up after 1 week. --- indra/llcrashlogger/llcrashlogger.cpp | 88 +++++++++++++++++++++++------------ indra/llcrashlogger/llcrashlogger.h | 1 + indra/newview/llappviewer.cpp | 30 +++++++++++- 3 files changed, 87 insertions(+), 32 deletions(-) (limited to 'indra') diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 078795f962..a91cf530b5 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -36,6 +36,8 @@ #include "llcrashlogger.h" #include "linden_common.h" +#include "lldate.h" +#include "llfile.h" #include "llstring.h" #include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME #include "llerror.h" @@ -153,54 +155,79 @@ std::string getStartupStateFromLog(std::string& sllog) return startup_state; } -void LLCrashLogger::gatherFiles() +void LLCrashLogger::findAndRenameLogFiles() { - updateApplication("Gathering logs..."); + // Find and rename the relevant log files so they won't be stomped on if + // SL is restarted before user sends crash report. + + std::string now = "." + LLDate::now().asString(); + + std::string stats_log_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); + std::string stats_log = stats_log_original; + stats_log.insert(stats_log.length() - 4, now); + if(LLFile::rename(stats_log_original, stats_log) == 0) + { + mFileMap["StatsLog"] = stats_log; + } + + std::string second_life_log_original; + std::string settings_file_original; - // Figure out the filename of the debug log - std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log"); + std::string db_file_name_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log"); + std::string db_file_name = db_file_name_original; + db_file_name.insert(db_file_name.length() - 4, now); + LLFile::rename(db_file_name_original, db_file_name); 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(mDebugLog, debug_log_file); - + LLSDSerialize::fromXML(mDebugLog, debug_log_file); 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()); - } - - llinfos << "Using log file from debug log " << mFileMap["SecondLifeLog"] << llendl; - llinfos << "Using settings file from debug log " << mFileMap["SettingsXml"] << llendl; + second_life_log_original = mDebugLog["SLLog"].asString(); + settings_file_original = mDebugLog["SettingsFilename"].asString(); } 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"); + second_life_log_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log"); + settings_file_original = 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; + second_life_log_original.replace(second_life_log_original.size() - 4, 4, ".old"); } + + std::string second_life_log = second_life_log_original; + std::string settings_file = settings_file_original; + second_life_log.insert(second_life_log.length() - 4, now); + settings_file.insert(settings_file.length() - 4, now); + if(LLFile::rename(second_life_log_original, second_life_log) == 0) + { + mFileMap["SecondLifeLog"] = second_life_log; + } + if(LLFile::rename(settings_file_original, settings_file) == 0) + { + mFileMap["SettingsXml"] = settings_file; + } +} + +void LLCrashLogger::gatherFiles() +{ + updateApplication("Gathering logs..."); + if(mDebugLog.has("CAFilename")) + { + LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); + } + else + { + LLCurl::setCAFile(gDirUtilp->getCAFile()); + } + gatherPlatformSpecificFiles(); //Use the debug log to reconstruct the URL to send the crash report to @@ -230,7 +257,6 @@ void LLCrashLogger::gatherFiles() mAltCrashHost = "https://login.agni.lindenlab.com:12043/crash/report"; mCrashInfo["DebugLog"] = mDebugLog; - mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); updateApplication("Encoding files..."); @@ -405,5 +431,7 @@ bool LLCrashLogger::init() LLAPRFile::remove( marker_file ); } + findAndRenameLogFiles(); + return true; } diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h index f8abe20597..a3cb17a958 100755 --- a/indra/llcrashlogger/llcrashlogger.h +++ b/indra/llcrashlogger/llcrashlogger.h @@ -48,6 +48,7 @@ public: S32 loadCrashBehaviorSetting(); void gatherFiles(); virtual void gatherPlatformSpecificFiles() {} + void findAndRenameLogFiles(); bool saveCrashBehaviorSetting(S32 crash_behavior); bool sendCrashLogs(); LLSD constructPostData(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 351c0cbae5..a5343bb522 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -81,7 +81,7 @@ #include "llvoicechannel.h" #include "llvoavatarself.h" #include "llsidetray.h" - +#include "lldate.h" #include "llweb.h" #include "llsecondlifeurls.h" @@ -102,6 +102,7 @@ // Third party library includes #include +#include #if LL_WINDOWS @@ -1242,12 +1243,37 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); - // remove any old breakpad minidump files from the log directory if (! isError()) { + // remove any old breakpad minidump files from the log directory std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); logdir += gDirUtilp->getDirDelimiter(); gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + + // remove any old log files saved from old crash reports. + const static std::string mask = "*.*.log"; + std::string filename; + while (gDirUtilp->getNextFileInDir(logdir, mask, filename, false)) + { + static const boost::regex + file_regex(".*\\.(.*)\\.log", boost::regex::extended); + boost::smatch match; + if(boost::regex_match(filename, match, file_regex) && match.size() > 1) + { + F64 date = LLDate(match[1]).secondsSinceEpoch(); + F64 age = LLDate::now().secondsSinceEpoch() - date; + if( date > 0.0 && age > 604800.0 ) + { + // Clean up files older than 1 week. + llinfos << "removing old log file " << filename << llendl; + LLFile::remove(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename)); + } + } + else + { + // ignore; + } + } } // *TODO - generalize this and move DSO wrangling to a helper class -brad -- cgit v1.2.3 From 29c068afc3779f58fa39f16ef9ddd7a9da29988b Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Wed, 2 Jun 2010 18:55:43 -0700 Subject: Finished task VPLAT-296: symbol files are packed in a tarball now instead of concatenated. --- indra/newview/CMakeLists.txt | 6 +++--- indra/newview/generate_breakpad_symbols.py | 25 ++++++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 64e2b40380..8e608327d8 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1808,20 +1808,20 @@ endif (INSTALL) if (PACKAGE) if (WINDOWS) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-windows.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2") set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) endif (WINDOWS) if (DARWIN) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-darwin.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2") set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") set(VIEWER_LIB_GLOB "*.dylib") endif (DARWIN) if (LINUX) set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") - set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-linux.breakpad.bz2") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2") set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index f281846918..3a5f34a5c3 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -38,7 +38,8 @@ import itertools import os import sys import subprocess -import bz2 +import tarfile +import StringIO def usage(): print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] @@ -59,12 +60,26 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) out, err = child.communicate() - return out + return (m,child.returncode, out, err) - out = bz2.BZ2File(viewer_symbol_file, 'w') + out = tarfile.open(viewer_symbol_file, 'w:bz2') - for symbols in map(dump_module, list_files()): - out.writelines(symbols) + for (filename,status,symbols,err) in itertools.imap(dump_module, list_files()): + if status == 0: + module_line = symbols[:symbols.index('\n')] + module_line = module_line.split() + hash_id = module_line[3] + module = ' '.join(module_line[4:]) + if sys.platform in ['win32', 'cygwin']: + mod_name = module[:module.rindex('.pdb')] + else: + mod_name = module + symbolfile = StringIO.StringIO(symbols) + info = tarfile.TarInfo("%(module)s/%(hash_id)s/%(mod_name)s.sym" % dict(module=module, hash_id=hash_id, mod_name=mod_name)) + info.size = symbolfile.len + out.addfile(info, symbolfile) + else: + print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) out.close() -- cgit v1.2.3 From 671092bcbc1a565e8b1cd140d005f246d325adc7 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 3 Jun 2010 13:22:50 -0700 Subject: Strip invalid characters from log files before adding into crash log llsd. --- indra/llcrashlogger/llcrashlogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 078795f962..51e5f14bfe 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -255,7 +255,7 @@ void LLCrashLogger::gatherFiles() trimSLLog(crash_info); } - mCrashInfo[(*itr).first] = rawstr_to_utf8(crash_info); + mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info)); } // Add minidump as binary. -- cgit v1.2.3 From 865887b12264701202a7668c011aa89668ed1839 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 3 Jun 2010 13:51:02 -0700 Subject: Finised a TODO left from recent viewer_manifest.py changes for the copy_l_viewer_manifest target. --- indra/newview/viewer_manifest.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 255995aea9..7639fcbe9b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -41,9 +41,12 @@ from llmanifest import LLManifest, main, proper_windows_path, path_ancestors class ViewerManifest(LLManifest): def is_packaging_viewer(self): - # This is overridden by the WindowsManifest sub-class, - # which has different behavior if it is not packaging the viewer. - return True + # Some commands, files will only be included + # if we are packaging the viewer on windows. + # This manifest is also used to copy + # files during the build (see copy_w_viewer_manifest + # and copy_l_viewer_manifest targets) + return 'package' in self.args['actions'] def construct(self): super(ViewerManifest, self).construct() @@ -169,13 +172,6 @@ class WindowsManifest(ViewerManifest): else: return ''.join(self.channel().split()) + '.exe' - def is_packaging_viewer(self): - # Some commands, files will only be included - # if we are packaging the viewer on windows. - # This manifest is also used to copy - # files during the build. - return 'package' in self.args['actions'] - def test_msvcrt_and_copy_action(self, src, dst): # This is used to test a dll manifest. # It is used as a temporary override during the construct method @@ -930,8 +926,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - # *TODO switch this to use self.is_packaging_viewer() once I understand all the consequences -brad - if self.args['buildtype'].lower() == 'release' and 'package' in self.args['actions']: + if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure -- cgit v1.2.3 From 5d68254c58e0a63086ea2e9a547ff5dd67300a12 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 3 Jun 2010 13:53:32 -0700 Subject: FIX VPLAT-248 fixed mising do-not-directly-run-secondlife-bin in linux symbol file. improper dependencies for the copy_l_viewer_manifest target were causing it to silently fail. --- indra/newview/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8e608327d8..228d56001a 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1717,7 +1717,7 @@ if (LINUX) ) add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) - add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}") + add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}" linux-crash-logger-target linux-updater-target) endif (LINUX) if (DARWIN) -- cgit v1.2.3 From 792b9d38cbf5fc5d03339c255a13912fa85bee51 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 3 Jun 2010 13:55:03 -0700 Subject: Added extra error checking to generate_breakpad_symbols.py so the failure in copy_l_viewer_manifest (fixed in changeset 4ae8723c7d33) won't be so silent in the future. --- indra/newview/generate_breakpad_symbols.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index 3a5f34a5c3..21db9ce152 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -37,6 +37,7 @@ import fnmatch import itertools import os import sys +import shlex import subprocess import tarfile import StringIO @@ -44,11 +45,27 @@ import StringIO def usage(): print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] +class MissingModuleError(Exception): + def __init__(self, modules): + Exception.__init__(self, "Failed to find required modules: %r" % modules) + self.modules = modules + def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): # print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + # split up list of viewer_exes + # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] + viewer_exes = shlex.split(viewer_exes) + + found_required = dict() + for required in viewer_exes: + found_required[required] = False + def matches(f): - return f in viewer_exes or fnmatch.fnmatch(f, libs_suffix) + if f in viewer_exes: + found_required[f] = True + return True + return fnmatch.fnmatch(f, libs_suffix) def list_files(): for (dirname, subdirs, filenames) in os.walk(viewer_dir): @@ -81,6 +98,12 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil else: print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) + missing_modules = [m for (m,_) in + itertools.ifilter(lambda (k,v): not v, found_required.iteritems()) + ] + if missing_modules: + raise MissingModuleError(missing_modules) + out.close() return 0 -- cgit v1.2.3 From 94a2a1a98bb22c88c87a6f1d3f5beb6bdc471d87 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Thu, 3 Jun 2010 18:21:06 -0700 Subject: Backed out renaming of log files (changeset 7357f4ef70df) executed: 'hg backout -r 7357f4ef70df --merge' --- indra/llcrashlogger/llcrashlogger.cpp | 88 ++++++++++++----------------------- indra/llcrashlogger/llcrashlogger.h | 1 - indra/newview/llappviewer.cpp | 30 +----------- 3 files changed, 32 insertions(+), 87 deletions(-) (limited to 'indra') diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index a91cf530b5..078795f962 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -36,8 +36,6 @@ #include "llcrashlogger.h" #include "linden_common.h" -#include "lldate.h" -#include "llfile.h" #include "llstring.h" #include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME #include "llerror.h" @@ -155,79 +153,54 @@ std::string getStartupStateFromLog(std::string& sllog) return startup_state; } -void LLCrashLogger::findAndRenameLogFiles() +void LLCrashLogger::gatherFiles() { - // Find and rename the relevant log files so they won't be stomped on if - // SL is restarted before user sends crash report. - - std::string now = "." + LLDate::now().asString(); - - std::string stats_log_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); - std::string stats_log = stats_log_original; - stats_log.insert(stats_log.length() - 4, now); - if(LLFile::rename(stats_log_original, stats_log) == 0) - { - mFileMap["StatsLog"] = stats_log; - } - - std::string second_life_log_original; - std::string settings_file_original; + updateApplication("Gathering logs..."); - std::string db_file_name_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log"); - std::string db_file_name = db_file_name_original; - db_file_name.insert(db_file_name.length() - 4, now); - LLFile::rename(db_file_name_original, db_file_name); + // Figure out the filename of the debug log + std::string db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log"); 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(mDebugLog, debug_log_file); + LLSDSerialize::fromXML(mDebugLog, debug_log_file); + mCrashInPreviousExec = mDebugLog["CrashNotHandled"].asBoolean(); - second_life_log_original = mDebugLog["SLLog"].asString(); - settings_file_original = mDebugLog["SettingsFilename"].asString(); + + mFileMap["SecondLifeLog"] = mDebugLog["SLLog"].asString(); + mFileMap["SettingsXml"] = mDebugLog["SettingsFilename"].asString(); + if(mDebugLog.has("CAFilename")) + { + LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); + } + else + { + LLCurl::setCAFile(gDirUtilp->getCAFile()); + } + + llinfos << "Using log file from debug log " << mFileMap["SecondLifeLog"] << llendl; + llinfos << "Using settings file from debug log " << mFileMap["SettingsXml"] << llendl; } else { // Figure out the filename of the second life log - second_life_log_original = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.log"); - settings_file_original = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); + 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 - second_life_log_original.replace(second_life_log_original.size() - 4, 4, ".old"); + std::string log_filename = mFileMap["SecondLifeLog"]; + log_filename.replace(log_filename.size() - 4, 4, ".old"); + mFileMap["SecondLifeLog"] = log_filename; } - - std::string second_life_log = second_life_log_original; - std::string settings_file = settings_file_original; - second_life_log.insert(second_life_log.length() - 4, now); - settings_file.insert(settings_file.length() - 4, now); - if(LLFile::rename(second_life_log_original, second_life_log) == 0) - { - mFileMap["SecondLifeLog"] = second_life_log; - } - if(LLFile::rename(settings_file_original, settings_file) == 0) - { - mFileMap["SettingsXml"] = settings_file; - } -} - -void LLCrashLogger::gatherFiles() -{ - updateApplication("Gathering logs..."); - if(mDebugLog.has("CAFilename")) - { - LLCurl::setCAFile(mDebugLog["CAFilename"].asString()); - } - else - { - LLCurl::setCAFile(gDirUtilp->getCAFile()); - } - gatherPlatformSpecificFiles(); //Use the debug log to reconstruct the URL to send the crash report to @@ -257,6 +230,7 @@ void LLCrashLogger::gatherFiles() mAltCrashHost = "https://login.agni.lindenlab.com:12043/crash/report"; mCrashInfo["DebugLog"] = mDebugLog; + mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); updateApplication("Encoding files..."); @@ -431,7 +405,5 @@ bool LLCrashLogger::init() LLAPRFile::remove( marker_file ); } - findAndRenameLogFiles(); - return true; } diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h index a3cb17a958..f8abe20597 100755 --- a/indra/llcrashlogger/llcrashlogger.h +++ b/indra/llcrashlogger/llcrashlogger.h @@ -48,7 +48,6 @@ public: S32 loadCrashBehaviorSetting(); void gatherFiles(); virtual void gatherPlatformSpecificFiles() {} - void findAndRenameLogFiles(); bool saveCrashBehaviorSetting(S32 crash_behavior); bool sendCrashLogs(); LLSD constructPostData(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a5343bb522..351c0cbae5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -81,7 +81,7 @@ #include "llvoicechannel.h" #include "llvoavatarself.h" #include "llsidetray.h" -#include "lldate.h" + #include "llweb.h" #include "llsecondlifeurls.h" @@ -102,7 +102,6 @@ // Third party library includes #include -#include #if LL_WINDOWS @@ -1243,37 +1242,12 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); + // remove any old breakpad minidump files from the log directory if (! isError()) { - // remove any old breakpad minidump files from the log directory std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); logdir += gDirUtilp->getDirDelimiter(); gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); - - // remove any old log files saved from old crash reports. - const static std::string mask = "*.*.log"; - std::string filename; - while (gDirUtilp->getNextFileInDir(logdir, mask, filename, false)) - { - static const boost::regex - file_regex(".*\\.(.*)\\.log", boost::regex::extended); - boost::smatch match; - if(boost::regex_match(filename, match, file_regex) && match.size() > 1) - { - F64 date = LLDate(match[1]).secondsSinceEpoch(); - F64 age = LLDate::now().secondsSinceEpoch() - date; - if( date > 0.0 && age > 604800.0 ) - { - // Clean up files older than 1 week. - llinfos << "removing old log file " << filename << llendl; - LLFile::remove(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename)); - } - } - else - { - // ignore; - } - } } // *TODO - generalize this and move DSO wrangling to a helper class -brad -- cgit v1.2.3 From c3892e9f368fd072fcd8a015af54f909e9189059 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 4 Jun 2010 12:57:32 -0700 Subject: Set CrashHostUrl if configured on start up to redirect freeze reports correctly. --- indra/newview/llappviewer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 351c0cbae5..842f3c7d1f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2516,6 +2516,15 @@ void LLAppViewer::writeSystemInfo() // 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; + + // 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 + // prior freeze. + std::string crashHostUrl = gSavedSettings.get("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } // Dump some debugging info LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") -- cgit v1.2.3 From edd224dc7b08ad72c0f36c5b0f24912fdf66ab1c Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 4 Jun 2010 14:13:33 -0700 Subject: Yet more error checking for linux symbol file generation. --- indra/newview/generate_breakpad_symbols.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index 21db9ce152..d94301d62e 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -35,6 +35,7 @@ import collections import fnmatch import itertools +import operator import os import sys import shlex @@ -51,15 +52,13 @@ class MissingModuleError(Exception): self.modules = modules def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): - # print "generate_breakpad_symbols: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) # split up list of viewer_exes # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] viewer_exes = shlex.split(viewer_exes) - found_required = dict() - for required in viewer_exes: - found_required[required] = False + found_required = dict([(module, False) for module in viewer_exes]) def matches(f): if f in viewer_exes: @@ -98,13 +97,28 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil else: print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) + out.close() + missing_modules = [m for (m,_) in itertools.ifilter(lambda (k,v): not v, found_required.iteritems()) ] if missing_modules: + print >> sys.stderr, "failed to generate %s" % viewer_symbol_file + os.remove(viewer_symbol_file) raise MissingModuleError(missing_modules) - out.close() + symbols = tarfile.open(viewer_symbol_file, 'r:bz2') + tarfile_members = symbols.getnames() + def match_module_basename(m): + return os.path.splitext(required_module)[0] == os.path.splitext(os.path.basename(m))[0] + for required_module in viewer_exes: + # there must be at least one .sym file in tarfile_members that matches each required module (ignoring file extensions) + if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): + print >> sys.stderr, "failed to find required %s in generated %s" % (required_module, viewer_symbol_file) + os.remove(viewer_symbol_file) + raise MissingModuleError([required_module]) + + print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes) return 0 -- cgit v1.2.3 From 4bbca7c086724da1af4f8cb6b22e6de8320a0b1b Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Tue, 8 Jun 2010 11:01:44 -0700 Subject: Fix for false positive in error checking symbol file generation on windows (MissingModuleError). --- indra/newview/generate_breakpad_symbols.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py index d94301d62e..1f42004bb7 100644 --- a/indra/newview/generate_breakpad_symbols.py +++ b/indra/newview/generate_breakpad_symbols.py @@ -109,12 +109,17 @@ def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_fil symbols = tarfile.open(viewer_symbol_file, 'r:bz2') tarfile_members = symbols.getnames() - def match_module_basename(m): - return os.path.splitext(required_module)[0] == os.path.splitext(os.path.basename(m))[0] + symbols.close() + for required_module in viewer_exes: - # there must be at least one .sym file in tarfile_members that matches each required module (ignoring file extensions) + def match_module_basename(m): + return os.path.splitext(required_module)[0].lower() \ + == os.path.splitext(os.path.basename(m))[0].lower() + # there must be at least one .sym file in tarfile_members that matches + # each required module (ignoring file extensions) if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): - print >> sys.stderr, "failed to find required %s in generated %s" % (required_module, viewer_symbol_file) + print >> sys.stderr, "failed to find required %s in generated %s" \ + % (required_module, viewer_symbol_file) os.remove(viewer_symbol_file) raise MissingModuleError([required_module]) -- cgit v1.2.3 From 163b767944caa4b2a474abf93e64eaeac1f02587 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 9 Jun 2010 15:45:35 -0700 Subject: Fix EXT-7432: if SL exits before SLVoice connection handshake completes, just kill the SLVoice process. Verified this is OK on windows. --- indra/newview/llvoicevivox.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index c6c155f0f0..74d0f0ef4b 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -396,19 +396,16 @@ void LLVivoxVoiceClient::init(LLPumpIO *pump) void LLVivoxVoiceClient::terminate() { - -// leaveAudioSession(); - logout(); - // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to. - // ms_sleep(2000); - connectorShutdown(); - closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. - - // This will do unpleasant things on windows. -// killGateway(); - - - + if(mConnected) + { + logout(); + connectorShutdown(); + closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. + } + else + { + killGateway(); + } } const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion() -- cgit v1.2.3 From b181dc15217c2fef234e308063d313d33ecb9df7 Mon Sep 17 00:00:00 2001 From: palange Date: Thu, 10 Jun 2010 17:09:32 -0700 Subject: Moved updater and crash_logger build dependencies from pacakge to sl-bin for mac --- indra/newview/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4ba8ce3e56..53c6369534 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1762,12 +1762,11 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-updater mac-crash-logger) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) check_message_template(package) - add_dependencies(package mac-updater mac-crash-logger) add_custom_command( TARGET package POST_BUILD -- cgit v1.2.3 From 59b4f7e25899e5f14cc6d1eb1f7f683ae6821657 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 11 Jun 2010 11:27:02 -0400 Subject: EXT-7824 FIXED Assert when changing folder type to "default" Not a serious assert error, but added "default" folder type to get rid of it. --- indra/newview/llviewerfoldertype.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 2859dabfba..56b5d7467c 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -45,10 +45,11 @@ struct ViewerFolderEntry : public LLDictionaryEntry ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type const std::string &icon_name_open, // name of the folder icon const std::string &icon_name_closed, - BOOL is_quiet // folder doesn't need a UI update when changed + BOOL is_quiet, // folder doesn't need a UI update when changed + const std::string &dictionary_name = empty_string // no reverse lookup needed on non-ensembles, so in most cases just leave this blank ) : - LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank + LLDictionaryEntry(dictionary_name), mNewCategoryName(new_category_name), mIconNameOpen(icon_name_open), mIconNameClosed(icon_name_closed), @@ -65,8 +66,11 @@ struct ViewerFolderEntry : public LLDictionaryEntry ) : LLDictionaryEntry(xui_name), + /* Just use default icons until we actually support ensembles mIconNameOpen(icon_name), mIconNameClosed(icon_name), + */ + mIconNameOpen("Inv_FolderOpen"), mIconNameClosed("Inv_FolderClosed"), mNewCategoryName(new_category_name), mIsQuiet(FALSE) { @@ -132,7 +136,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE)); addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE)); - addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() -- cgit v1.2.3