diff options
author | Kyle Machulis <qdot@lindenlab.com> | 2007-11-20 23:42:48 +0000 |
---|---|---|
committer | Kyle Machulis <qdot@lindenlab.com> | 2007-11-20 23:42:48 +0000 |
commit | 2e7c0d973ed28d732ea19762099ed3c55123780e (patch) | |
tree | 36b04301d325e07075880a8a64166c5284d1d61f /indra/mac_crash_logger/llcrashloggermac.cpp | |
parent | 5356b917545d43df5537128245ee5b786b705b90 (diff) |
svn merge -r74104:74124 svn+ssh://svn/svn/linden/branches/crash-logger-cleanup-merge-6
Diffstat (limited to 'indra/mac_crash_logger/llcrashloggermac.cpp')
-rw-r--r-- | indra/mac_crash_logger/llcrashloggermac.cpp | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp new file mode 100644 index 0000000000..ba50af9d00 --- /dev/null +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -0,0 +1,310 @@ +/** + * @file llcrashloggermac.cpp + * @brief Mac OSX crash logger implementation + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2007, 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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 "llcrashloggermac.h" + +#include <Carbon/Carbon.h> +#include <iostream> +#include <sstream> + +#include "boost/tokenizer.hpp" + +#include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME +#include "llerror.h" +#include "llfile.h" +#include "lltimer.h" +#include "llstring.h" +#include "lldir.h" +#include "llsdserialize.h" + +#define MAX_LOADSTRING 100 +const char* const SETTINGS_FILE_HEADER = "version"; +const S32 SETTINGS_FILE_VERSION = 101; + +// Windows Message Handlers + +BOOL gFirstDialog = TRUE; // Are we currently handling the Send/Don't Send dialog? +FILE *gDebugFile = NULL; + +WindowRef gWindow = NULL; +EventHandlerRef gEventHandler = NULL; +LLString gUserNotes = ""; +bool gSendReport = false; +bool gRememberChoice = false; +IBNibRef nib = NULL; + +OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) +{ + OSStatus result = eventNotHandledErr; + OSStatus err; + UInt32 evtClass = GetEventClass(event); + UInt32 evtKind = GetEventKind(event); + if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) + { + HICommand cmd; + err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); + + + + if(err == noErr) + { + //Get the value of the checkbox + ControlID id; + ControlRef checkBox = NULL; + id.signature = 'remb'; + id.id = 0; + err = GetControlByID(gWindow, &id, &checkBox); + + if(err == noErr) + { + if(GetControl32BitValue(checkBox) == kControlCheckBoxCheckedValue) + { + gRememberChoice = true; + } + else + { + gRememberChoice = false; + } + } + switch(cmd.commandID) + { + case kHICommandOK: + { + char buffer[65535]; /* Flawfinder: ignore */ + Size size = sizeof(buffer) - 1; + ControlRef textField = NULL; + + id.signature = 'text'; + id.id = 0; + + err = GetControlByID(gWindow, &id, &textField); + if(err == noErr) + { + // Get the user response text + err = GetControlData(textField, kControlNoPart, kControlEditTextTextTag, size, (Ptr)buffer, &size); + } + if(err == noErr) + { + // Make sure the string is terminated. + buffer[size] = 0; + //setUserText(buffer); + llinfos << buffer << llendl; + } + + // Send the report. + + QuitAppModalLoopForWindow(gWindow); + gSendReport = true; + result = noErr; + } + break; + + case kHICommandCancel: + QuitAppModalLoopForWindow(gWindow); + result = noErr; + break; + } + } + } + + return(result); +} + + +LLCrashLoggerMac::LLCrashLoggerMac(void) +{ +} + +LLCrashLoggerMac::~LLCrashLoggerMac(void) +{ +} + +bool LLCrashLoggerMac::init(void) +{ + bool ok = LLCrashLogger::init(); + if(!ok) return false; + // Real UI... + OSStatus err; + + err = CreateNibReference(CFSTR("CrashReporter"), &nib); + + if(err == noErr) + { + err = CreateWindowFromNib(nib, CFSTR("CrashReporter"), &gWindow); + } + + if(err == noErr) + { + // Set focus to the edit text area + ControlRef textField = NULL; + ControlID id; + + id.signature = 'text'; + id.id = 0; + + // Don't set err if any of this fails, since it's non-critical. + if(GetControlByID(gWindow, &id, &textField) == noErr) + { + SetKeyboardFocus(gWindow, textField, kControlFocusNextPart); + } + } + + if(err == noErr) + { + ShowWindow(gWindow); + } + + if(err == noErr) + { + // Set up an event handler for the window. + EventTypeSpec handlerEvents[] = + { + { kEventClassCommand, kEventCommandProcess } + }; + + InstallWindowEventHandler( + gWindow, + NewEventHandlerUPP(dialogHandler), + GetEventTypeCount (handlerEvents), + handlerEvents, + 0, + &gEventHandler); + } + return true; +} + +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; + LLString mBuf; + // Try the 10.3 path first... + LLString dw_file_name = LLString(path) + LLString("/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 = LLString(path) + LLString("/Second Life.crash.log"); + res = stat(dw_file_name.c_str(), &dw_stat); + } + + if (!res) + { + std::ifstream fp(dw_file_name.c_str()); + std::stringstream str; + if(!fp.is_open()) return; + str << fp.rdbuf(); + mBuf = str.str(); + + // 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); + } + mDebugLog["CrashInfo"] = mBuf; + } + else + { + llwarns << "Couldn't find any CrashReporter files..." << llendl; + } + } + } +} + +bool LLCrashLoggerMac::mainLoop() +{ + OSStatus err = noErr; + + if(err == noErr) + { + RunAppModalLoopForWindow(gWindow); + } + + if(gRememberChoice) + { + if(gSendReport) saveCrashBehaviorSetting(CRASH_BEHAVIOR_ALWAYS_SEND); + else saveCrashBehaviorSetting(CRASH_BEHAVIOR_NEVER_SEND); + } + + if(gSendReport) + { + sendCrashLogs(); + } + + if(gWindow != NULL) + { + DisposeWindow(gWindow); + } + + if(nib != NULL) + { + DisposeNibReference(nib); + } + + return true; +} + +void LLCrashLoggerMac::updateApplication(LLString message) +{ + LLCrashLogger::updateApplication(); +} + +bool LLCrashLoggerMac::cleanup() +{ + return true; +} |