Breakpad: untested update to linux/mac specific parts of llappviewer
This commit is contained in:
@@ -46,27 +46,6 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
#if LL_LINUX
|
|
||||||
# include <dlfcn.h> // RTLD_LAZY
|
|
||||||
# include <execinfo.h> // backtrace - glibc only
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <dirent.h>
|
|
||||||
# include <boost/algorithm/string.hpp>
|
|
||||||
#elif LL_SOLARIS
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# include <ucontext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LL_ELFBIN
|
|
||||||
# ifdef __GNUC__
|
|
||||||
# include <cxxabi.h> // for symbol demangling
|
|
||||||
# endif
|
|
||||||
# include "ELFIO/ELFIO.h" // for better backtraces
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LL_DBUS_ENABLED
|
#if LL_DBUS_ENABLED
|
||||||
# include "llappviewerlinux_api_dbus.h"
|
# include "llappviewerlinux_api_dbus.h"
|
||||||
|
|
||||||
@@ -90,8 +69,9 @@ static void exceptionTerminateHandler()
|
|||||||
// reinstall default terminate() handler in case we re-terminate.
|
// reinstall default terminate() handler in case we re-terminate.
|
||||||
if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);
|
if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);
|
||||||
// treat this like a regular viewer crash, with nice stacktrace etc.
|
// treat this like a regular viewer crash, with nice stacktrace etc.
|
||||||
LLAppViewer::handleSyncViewerCrash();
|
long *null_ptr;
|
||||||
LLAppViewer::handleViewerCrash();
|
null_ptr = 0;
|
||||||
|
*null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
|
||||||
// we've probably been killed-off before now, but...
|
// we've probably been killed-off before now, but...
|
||||||
gOldTerminateHandler(); // call old terminate() handler
|
gOldTerminateHandler(); // call old terminate() handler
|
||||||
}
|
}
|
||||||
@@ -114,7 +94,6 @@ int main( int argc, char **argv )
|
|||||||
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
||||||
// install crash handlers
|
// install crash handlers
|
||||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||||
viewer_app_ptr->setSyncErrorHandler(LLAppViewer::handleSyncViewerCrash);
|
|
||||||
|
|
||||||
bool ok = viewer_app_ptr->init();
|
bool ok = viewer_app_ptr->init();
|
||||||
if(!ok)
|
if(!ok)
|
||||||
@@ -144,201 +123,6 @@ int main( int argc, char **argv )
|
|||||||
return 0;
|
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()
|
LLAppViewerLinux::LLAppViewerLinux()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -355,7 +139,17 @@ bool LLAppViewerLinux::init()
|
|||||||
// really early in app startup!
|
// really early in app startup!
|
||||||
if (!g_thread_supported ()) g_thread_init (NULL);
|
if (!g_thread_supported ()) g_thread_init (NULL);
|
||||||
|
|
||||||
return LLAppViewer::init();
|
bool success = LLAppViewer::init();
|
||||||
|
|
||||||
|
#if LL_SEND_CRASH_REPORTS
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
LLAppViewer* pApp = LLAppViewer::instance();
|
||||||
|
pApp->initCrashReporting();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLAppViewerLinux::restoreErrorTrap()
|
bool LLAppViewerLinux::restoreErrorTrap()
|
||||||
@@ -547,101 +341,10 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
|
|||||||
}
|
}
|
||||||
#endif // LL_DBUS_ENABLED
|
#endif // LL_DBUS_ENABLED
|
||||||
|
|
||||||
void LLAppViewerLinux::handleSyncCrashTrace()
|
void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
|
||||||
{
|
{
|
||||||
// This backtrace writes into stack_trace.log
|
// Singu Note: this is where original code forks crash logger process.
|
||||||
# if LL_ELFBIN
|
// Singularity doesn't need it
|
||||||
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->getAppRODataDir();
|
|
||||||
cmd += gDirUtilp->getDirDelimiter();
|
|
||||||
#if LL_LINUX
|
|
||||||
cmd += "linux-crash-logger.bin";
|
|
||||||
#elif LL_SOLARIS
|
|
||||||
cmd += "solaris-crash-logger";
|
|
||||||
#else
|
|
||||||
# error Unknown platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(reportFreeze)
|
|
||||||
{
|
|
||||||
char* const cmdargv[] =
|
|
||||||
{(char*)cmd.c_str(),
|
|
||||||
(char*)"-previous",
|
|
||||||
NULL};
|
|
||||||
|
|
||||||
fflush(NULL); // flush all buffers before the child inherits them
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0)
|
|
||||||
{ // child
|
|
||||||
execv(cmd.c_str(), cmdargv); /* Flawfinder: Ignore */
|
|
||||||
llwarns << "execv failure when trying to start " << cmd << llendl;
|
|
||||||
_exit(1); // avoid atexit()
|
|
||||||
} else {
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
// wait for child proc to die
|
|
||||||
int childExitStatus;
|
|
||||||
waitpid(pid, &childExitStatus, 0);
|
|
||||||
} else {
|
|
||||||
llwarns << "fork failure." << llendl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING);
|
|
||||||
|
|
||||||
// Always generate the report, have the logger do the asking, and
|
|
||||||
// don't wait for the logger before exiting (-> total cleanup).
|
|
||||||
if (CRASH_BEHAVIOR_NEVER_SEND != cb)
|
|
||||||
{
|
|
||||||
// launch the actual crash logger
|
|
||||||
const char* ask_dialog = "-dialog";
|
|
||||||
if (CRASH_BEHAVIOR_ASK != cb)
|
|
||||||
ask_dialog = ""; // omit '-dialog' option
|
|
||||||
const char * cmdargv[] =
|
|
||||||
{cmd.c_str(),
|
|
||||||
ask_dialog,
|
|
||||||
"-user",
|
|
||||||
(char*)LLViewerLogin::getInstance()->getGridLabel().c_str(),
|
|
||||||
"-name",
|
|
||||||
LLAppViewer::instance()->getSecondLifeTitle().c_str(),
|
|
||||||
NULL};
|
|
||||||
fflush(NULL);
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == 0)
|
|
||||||
{ // child
|
|
||||||
execv(cmd.c_str(), (char* const*) cmdargv); /* Flawfinder: ignore */
|
|
||||||
llwarns << "execv failure when trying to start " << cmd << llendl;
|
|
||||||
_exit(1); // avoid atexit()
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
// DO NOT wait for child proc to die; we want
|
|
||||||
// the logger to outlive us while we quit to
|
|
||||||
// free up the screen/keyboard/etc.
|
|
||||||
////int childExitStatus;
|
|
||||||
////waitpid(pid, &childExitStatus, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
llwarns << "fork failure." << llendl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sometimes signals don't seem to quit the viewer. Also, we may
|
|
||||||
// have been called explicitly instead of from a signal handler.
|
|
||||||
// Make sure we exit so as to not totally confuse the user.
|
|
||||||
_exit(1); // avoid atexit(), else we may re-crash in dtors.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +379,6 @@ bool LLAppViewerLinux::beingDebugged()
|
|||||||
base += 1;
|
base += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//should valgrind be added here?
|
|
||||||
if (strcmp(base, "gdb") == 0)
|
if (strcmp(base, "gdb") == 0)
|
||||||
{
|
{
|
||||||
debugged = yes;
|
debugged = yes;
|
||||||
@@ -693,6 +395,8 @@ bool LLAppViewerLinux::beingDebugged()
|
|||||||
bool LLAppViewerLinux::initLogging()
|
bool LLAppViewerLinux::initLogging()
|
||||||
{
|
{
|
||||||
// Remove the last stack trace, if any
|
// 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 =
|
std::string old_stack_file =
|
||||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
|
gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");
|
||||||
LLFile::remove(old_stack_file);
|
LLFile::remove(old_stack_file);
|
||||||
@@ -739,6 +443,7 @@ std::string LLAppViewerLinux::generateSerialNumber()
|
|||||||
|
|
||||||
// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
|
// trawl /dev/disk/by-uuid looking for a good-looking UUID to grab
|
||||||
std::string this_name;
|
std::string this_name;
|
||||||
|
|
||||||
LLDirIterator iter(uuiddir, "*");
|
LLDirIterator iter(uuiddir, "*");
|
||||||
while (iter.next(this_name))
|
while (iter.next(this_name))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ protected:
|
|||||||
virtual bool beingDebugged();
|
virtual bool beingDebugged();
|
||||||
|
|
||||||
virtual bool restoreErrorTrap();
|
virtual bool restoreErrorTrap();
|
||||||
virtual void handleCrashReporting(bool reportFreeze);
|
virtual void initCrashReporting(bool reportFreeze);
|
||||||
virtual void handleSyncCrashTrace();
|
|
||||||
|
|
||||||
virtual bool initLogging();
|
virtual bool initLogging();
|
||||||
virtual bool initParseCommandLine(LLCommandLineParser& clp);
|
virtual bool initParseCommandLine(LLCommandLineParser& clp);
|
||||||
|
|||||||
@@ -69,6 +69,19 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void exceptionTerminateHandler()
|
||||||
|
{
|
||||||
|
// reinstall default terminate() handler in case we re-terminate.
|
||||||
|
if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);
|
||||||
|
// treat this like a regular viewer crash, with nice stacktrace etc.
|
||||||
|
long *null_ptr;
|
||||||
|
null_ptr = 0;
|
||||||
|
*null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
|
||||||
|
//LLAppViewer::handleViewerCrash();
|
||||||
|
// we've probably been killed-off before now, but...
|
||||||
|
gOldTerminateHandler(); // call old terminate() handler
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
#if LL_SOLARIS && defined(__sparc)
|
#if LL_SOLARIS && defined(__sparc)
|
||||||
@@ -262,11 +275,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
|
|||||||
return reset_count == 0;
|
return reset_count == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAppViewerMacOSX::handleSyncCrashTrace()
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
||||||
EventRef inEvent,
|
EventRef inEvent,
|
||||||
void* inUserData)
|
void* inUserData)
|
||||||
@@ -294,122 +302,10 @@ static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
|
|||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
|
void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
|
||||||
{
|
{
|
||||||
// This used to use fork&exec, but is switched to LSOpenApplication to
|
// Singu Note: this is where original code forks crash logger process.
|
||||||
// Make sure the crash reporter launches in front of the SL window.
|
// Singularity doesn't need it
|
||||||
|
|
||||||
std::string command_str;
|
|
||||||
//command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app";
|
|
||||||
command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger";
|
|
||||||
|
|
||||||
FSRef appRef;
|
|
||||||
Boolean isDir = 0;
|
|
||||||
OSStatus os_result = FSPathMakeRef((UInt8*)command_str.c_str(),
|
|
||||||
&appRef,
|
|
||||||
&isDir);
|
|
||||||
if(os_result >= 0)
|
|
||||||
{
|
|
||||||
LSApplicationParameters appParams;
|
|
||||||
memset(&appParams, 0, sizeof(appParams));
|
|
||||||
appParams.version = 0;
|
|
||||||
appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic;
|
|
||||||
appParams.application = &appRef;
|
|
||||||
|
|
||||||
if(reportFreeze)
|
|
||||||
{
|
|
||||||
// Make sure freeze reporting launches the crash logger synchronously, lest
|
|
||||||
// Log files get changed by SL while the logger is running.
|
|
||||||
|
|
||||||
// *NOTE:Mani A better way - make a copy of the data that the crash reporter will send
|
|
||||||
// and let SL go about its business. This way makes the mac work like windows and linux
|
|
||||||
// and is the smallest patch for the issue.
|
|
||||||
sCrashReporterIsRunning = false;
|
|
||||||
ProcessSerialNumber o_psn;
|
|
||||||
|
|
||||||
static EventHandlerRef sCarbonEventsRef = NULL;
|
|
||||||
static const EventTypeSpec kEvents[] =
|
|
||||||
{
|
|
||||||
{ kEventClassApplication, kEventAppTerminated }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Install the handler to detect crash logger termination
|
|
||||||
InstallEventHandler(GetApplicationEventTarget(),
|
|
||||||
(EventHandlerUPP) CarbonEventHandler,
|
|
||||||
GetEventTypeCount(kEvents),
|
|
||||||
kEvents,
|
|
||||||
&o_psn,
|
|
||||||
&sCarbonEventsRef
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove, temporarily the quit handler - which has *crash* behavior before
|
|
||||||
// the mainloop gets running!
|
|
||||||
AERemoveEventHandler(kCoreEventClass,
|
|
||||||
kAEQuitApplication,
|
|
||||||
NewAEEventHandlerUPP(AEQuitHandler),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// Launch the crash reporter.
|
|
||||||
os_result = LSOpenApplication(&appParams, &o_psn);
|
|
||||||
|
|
||||||
if(os_result >= 0)
|
|
||||||
{
|
|
||||||
sCrashReporterIsRunning = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(sCrashReporterIsRunning)
|
|
||||||
{
|
|
||||||
RunApplicationEventLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-install the apps quit handler.
|
|
||||||
AEInstallEventHandler(kCoreEventClass,
|
|
||||||
kAEQuitApplication,
|
|
||||||
NewAEEventHandlerUPP(AEQuitHandler),
|
|
||||||
0,
|
|
||||||
false);
|
|
||||||
|
|
||||||
// Remove the crash reporter quit handler.
|
|
||||||
RemoveEventHandler(sCarbonEventsRef);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appParams.flags |= kLSLaunchAsync;
|
|
||||||
clear_signals();
|
|
||||||
|
|
||||||
ProcessSerialNumber o_psn;
|
|
||||||
os_result = LSOpenApplication(&appParams, &o_psn);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!reportFreeze)
|
|
||||||
{
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO:palmer REMOVE THIS VERY SOON. THIS WILL NOT BE IN VIEWER 2.0
|
|
||||||
// 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;
|
|
||||||
LLDirIterator iter(pathname, mask);
|
|
||||||
while(iter.next(file_name))
|
|
||||||
{
|
|
||||||
LLFile::remove(pathname + file_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LLAppViewerMacOSX::generateSerialNumber()
|
std::string LLAppViewerMacOSX::generateSerialNumber()
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool restoreErrorTrap();
|
virtual bool restoreErrorTrap();
|
||||||
virtual void handleCrashReporting(bool reportFreeze);
|
virtual void initCrashReporting(bool reportFreeze);
|
||||||
virtual void handleSyncCrashTrace();
|
|
||||||
|
|
||||||
std::string generateSerialNumber();
|
std::string generateSerialNumber();
|
||||||
virtual bool initParseCommandLine(LLCommandLineParser& clp);
|
virtual bool initParseCommandLine(LLCommandLineParser& clp);
|
||||||
|
|||||||
Reference in New Issue
Block a user