diff options
Diffstat (limited to 'indra/llcommon/llapp.cpp')
-rw-r--r-- | indra/llcommon/llapp.cpp | 275 |
1 files changed, 57 insertions, 218 deletions
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index eebd5ed0a6..6b2d1b7c20 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -2,36 +2,34 @@ * @file llapp.cpp * @brief Implementation of the LLApp class. * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, Linden Research, Inc. * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. + * 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 * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * 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 * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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 <cstdlib> - -#ifdef LL_DARWIN -#include <sys/types.h> -#include <unistd.h> -#include <sys/sysctl.h> -#endif - #include "linden_common.h" #include "llapp.h" @@ -43,11 +41,8 @@ #include "lllivefile.h" #include "llmemory.h" #include "llstl.h" // for DeletePointer() -#include "llstring.h" #include "lleventtimer.h" -#include "google_breakpad/exception_handler.h" - // // Signal handling // @@ -56,22 +51,11 @@ #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 <signal.h> # include <unistd.h> // 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 unix_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; @@ -97,6 +81,7 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status LLAppErrorHandler LLApp::sErrorHandler = NULL; +LLAppErrorHandler LLApp::sSyncErrorHandler = NULL; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -138,12 +123,7 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - - 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); + } LLApp::LLApp(LLErrorThread *error_thread) : @@ -172,8 +152,6 @@ LLApp::~LLApp() delete mThreadErrorp; mThreadErrorp = NULL; } - - if(mExceptionHandler != 0) delete mExceptionHandler; LLCommon::cleanupClass(); } @@ -284,18 +262,19 @@ 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; - mExceptionHandler = new google_breakpad::ExceptionHandler( - L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL); - } - #else // // Start up signal handling. @@ -303,49 +282,9 @@ 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(); - - // Add google breakpad exception handler configured for Darwin/Linux. - bool installHandler = true; -#ifdef LL_DARWIN - // For the special case of Darwin, we do not want to install the handler if - // the process is being debugged as the app will exit with value ABRT (6) if - // we do. Unfortunately, the code below which performs that test relies on - // the structure kinfo_proc which has been tagged by apple as an unstable - // API. We disable this test for shipping versions to avoid conflicts with - // future releases of Darwin. This test is really only needed for developers - // starting the app from a debugger anyway. - #ifndef LL_RELEASE_FOR_DOWNLOAD - int mib[4]; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - struct kinfo_proc info; - memset(&info, 0, sizeof(info)); - - size_t size = sizeof(info); - int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); - if((result == 0) || (errno == ENOMEM)) - { - // P_TRACED flag is set, so this process is being debugged; do not install - // the handler - if(info.kp_proc.p_flag & P_TRACED) installHandler = false; - } - else - { - // Failed to discover if the process is being debugged; default to - // installing the handler. - installHandler = true; - } - #endif -#endif - if(installHandler && (mExceptionHandler == 0)) - { - std::string dumpPath = "/tmp/"; - mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); - } + #endif startErrorThread(); @@ -371,6 +310,21 @@ 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() { @@ -383,6 +337,7 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } + // static void LLApp::setStatus(EAppStatus status) { @@ -393,27 +348,15 @@ void LLApp::setStatus(EAppStatus status) // static void LLApp::setError() { - // set app status to ERROR so that the LLErrorThread notices - setStatus(APP_STATUS_ERROR); + if (!isError()) + { + // perform any needed synchronous error-handling + runSyncErrorHandler(); + // set app status to ERROR so that the LLErrorThread notices + setStatus(APP_STATUS_ERROR); + } } -void LLApp::setMiniDumpDir(const std::string &path) -{ - if(mExceptionHandler == 0) return; -#ifdef LL_WINDOWS - 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 -} - -void LLApp::writeMiniDump() -{ - if(mExceptionHandler == 0) return; - mExceptionHandler->WriteMinidump(); -} // static void LLApp::setQuitting() @@ -644,7 +587,6 @@ void setup_signals() // Asynchronous signals that result in core sigaction(SIGQUIT, &act, NULL); - } void clear_signals() @@ -823,107 +765,4 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } -bool unix_post_minidump_callback(const char *dump_dir, - const char *minidump_id, - void *context, bool succeeded) -{ - // Copy minidump file path into fixed buffer in the app instance to avoid - // heap allocations in a crash handler. - - // path format: <dump_dir>/<minidump_id>.dmp - int dirPathLength = strlen(dump_dir); - int idLength = strlen(minidump_id); - - // The path must not be truncated. - llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); - - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - strncpy(path, dump_dir, remaining); - remaining -= dirPathLength; - path += dirPathLength; - if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') - { - *path++ = '/'; - --remaining; - } - if (remaining > 0) - { - strncpy(path, minidump_id, remaining); - remaining -= idLength; - path += idLength; - strncpy(path, ".dmp", remaining); - } - - llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; - LLApp::runErrorHandler(); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - clear_signals(); - return false; -#else - return true; -#endif -} #endif // !WINDOWS - -#ifdef LL_WINDOWS -bool windows_post_minidump_callback(const wchar_t* dump_path, - const wchar_t* minidump_id, - void* context, - EXCEPTION_POINTERS* exinfo, - MDRawAssertionInfo* assertion, - bool succeeded) -{ - char * path = LLApp::instance()->getMiniDumpFilename(); - S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; - size_t bytesUsed; - - bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') - { - *path++ = '\\'; - --remaining; - } - if(remaining > 0) - { - bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining)); - remaining -= bytesUsed; - path += bytesUsed; - } - if(remaining > 0) - { - strncpy(path, ".dmp", remaining); - } - - 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 - // 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); - } - -#ifndef LL_RELEASE_FOR_DOWNLOAD - return false; -#else - return true; -#endif -} -#endif |