summaryrefslogtreecommitdiff
path: root/indra/llcommon/llapp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llapp.cpp')
-rw-r--r--indra/llcommon/llapp.cpp275
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