diff options
-rw-r--r-- | indra/newview/llappdelegate-objc.mm | 43 | ||||
-rw-r--r-- | indra/newview/llappviewermacosx-for-objc.h | 21 | ||||
-rw-r--r-- | indra/newview/llappviewermacosx.cpp | 45 | ||||
-rw-r--r-- | indra/newview/llviewerregion.cpp | 19 |
4 files changed, 109 insertions, 19 deletions
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 82e49540a4..ba697d0f77 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -199,10 +199,34 @@ - (NSString *)applicationLogForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { infos("Reached applicationLogForBugsplatStartupManager"); - // Apparently this override method only contributes the User Description - // field of BugSplat's All Crashes table. Despite the method name, it - // would seem to be a bad place to try to stuff all of SecondLife.log. - return [NSString stringWithCString:getFatalMessage().c_str() + // This strangely-named override method contributes the User Description + // metadata field. + return [NSString stringWithCString:CrashMetadata_instance().fatalMessage.c_str() + encoding:NSUTF8StringEncoding]; +} + +- (NSString *)applicationKeyForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager signal:(NSString *)signal exceptionName:(NSString *)exceptionName exceptionReason:(NSString *)exceptionReason { + // TODO: exceptionName, exceptionReason + + // Windows sends location within region as well, but that's because + // BugSplat for Windows intercepts crashes during the same run, and that + // information can be queried once. On the Mac, any metadata we have is + // written (and rewritten) to the static_debug_info.log file that we read + // at the start of the next viewer run. It seems ridiculously expensive to + // rewrite that file on every frame in which the avatar moves. + return [NSString stringWithCString:CrashMetadata_instance().regionName.c_str() + encoding:NSUTF8StringEncoding]; +} + +- (NSString *)defaultUserNameForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { + return [NSString stringWithCString:CrashMetadata_instance().agentFullname.c_str() + encoding:NSUTF8StringEncoding]; +} + +- (NSString *)defaultUserEmailForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { + // Use the email field for OS version, just as we do on Windows, until + // BugSplat provides more metadata fields. + return [NSString stringWithCString:CrashMetadata_instance().OSInfo.c_str() encoding:NSUTF8StringEncoding]; } @@ -212,11 +236,12 @@ } - (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { - // We get the *old* log file pathname (for SecondLife.old) because it's on - // the run *following* the crash that BugsplatStartupManager notices that - // the previous run crashed and calls this override. By that time, we've - // already renamed SecondLife.log to SecondLife.old. - std::string logfile = getOldLogFilePathname(); + std::string logfile = CrashMetadata_instance().logFilePathname; + // Still to do: + // userSettingsPathname + // staticDebugPathname + // but the BugsplatMac version 1.0.5 BugsplatStartupManagerDelegate API + // doesn't yet provide a way to attach more than one file. NSString *ns_logfile = [NSString stringWithCString:logfile.c_str() encoding:NSUTF8StringEncoding]; NSData *data = [NSData dataWithContentsOfFile:ns_logfile]; diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h index ac85d7e8c3..79da453cbe 100644 --- a/indra/newview/llappviewermacosx-for-objc.h +++ b/indra/newview/llappviewermacosx-for-objc.h @@ -29,9 +29,24 @@ void handleUrl(const char* url_utf8); bool pumpMainLoop(); void handleQuit(); void cleanupViewer(); -std::string getOldLogFilePathname(); -std::string getFatalMessage(); -std::string getAgentFullname(); void infos(const std::string& message); +// This struct is malleable; it only serves as a way to convey a number of +// fields from llappviewermacosx.cpp's CrashMetadata_instance() function to the +// consuming functions in llappdelegate-objc.mm. As long as both those sources +// are compiled with this same header, the content and order of CrashMetadata +// can change as needed. +struct CrashMetadata +{ + std::string logFilePathname; + std::string userSettingsPathname; + std::string staticDebugPathname; + std::string OSInfo; + std::string agentFullname; + std::string regionName; + std::string fatalMessage; +}; + +CrashMetadata& CrashMetadata_instance(); + #endif /* ! defined(LL_LLAPPVIEWERMACOSX_FOR_OBJC_H) */ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index c3a3c3284a..7f7284a796 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -39,6 +39,7 @@ #include "llappviewermacosx-for-objc.h" #include "llwindowmacosx-objc.h" #include "llcommandlineparser.h" +#include "llsdserialize.h" #include "llviewernetwork.h" #include "llviewercontrol.h" @@ -53,6 +54,7 @@ #endif #include <vector> #include <exception> +#include <fstream> #include "lldir.h" #include <signal.h> @@ -150,19 +152,48 @@ void cleanupViewer() gViewerAppPtr = NULL; } -std::string getOldLogFilePathname() +// The BugsplatMac API is structured as a number of different method +// overrides, each returning a different piece of metadata. But since we +// obtain such metadata by opening and parsing a file, it seems ridiculous to +// reopen and reparse it for every individual string desired. What we want is +// to open and parse the file once, retaining the data for subsequent +// requests. That's why this is an LLSingleton. +// Another approach would be to provide a function that simply returns +// CrashMetadata, storing the struct in LLAppDelegate, but nat doesn't know +// enough Objective-C++ to code that. We'd still have to detect which of the +// method overrides is called first so that the results are order-insensitive. +class CrashMetadataSingleton: public CrashMetadata, public LLSingleton<CrashMetadataSingleton> { - return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.old"); -} + LLSINGLETON(CrashMetadataSingleton); +}; -std::string getFatalMessage() +// Populate the fields of our public base-class struct. +CrashMetadataSingleton::CrashMetadataSingleton() { - return LLError::getFatalMessage(); + // Note: we depend on being able to read the static_debug_info.log file + // from the *previous* run before we overwrite it with the new one for + // *this* run. LLAppViewer initialization must happen in the Right Order. + staticDebugPathname = *gViewerAppPtr->getStaticDebugFile(); + std::ifstream static_file(staticDebugPathname); + LLSD info; + if (static_file.is_open() && + LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED)) + { + logFilePathname = info["SLLog"].asString(); + userSettingsPathname = info["SettingsFilename"].asString(); + OSInfo = info["OSInfo"].asString(); + agentFullname = info["LoginName"].asString(); + // Translate underscores back to spaces + LLStringUtil::replaceChar(agentFullname, '_', ' '); + regionName = info["CurrentRegion"].asString(); + fatalMessage = info["FatalMessage"].asString(); + } } -std::string getAgentFullname() +// Avoid having to compile all of our LLSingleton machinery in Objective-C++. +CrashMetadata& CrashMetadata_instance() { - return gAgentAvatarp? gAgentAvatarp->getFullname() : std::string(); + return CrashMetadataSingleton::instance(); } void infos(const std::string& message) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b759c2a3ab..ca452fc766 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -44,6 +44,7 @@ #include "llagent.h" #include "llagentcamera.h" +#include "llappviewer.h" #include "llavatarrenderinfoaccountant.h" #include "llcallingcard.h" #include "llcommandhandler.h" @@ -104,6 +105,18 @@ typedef std::map<std::string, std::string> CapabilityMap; static void log_capabilities(const CapabilityMap &capmap); +namespace +{ + +void newRegionEntry(LLViewerRegion& region) +{ + LL_INFOS("LLViewerRegion") << "Entering region [" << region.getName() << "]" << LL_ENDL; + gDebugInfo["CurrentRegion"] = region.getName(); + LLAppViewer::instance()->writeDebugInfo(); +} + +} // anonymous namespace + // support for secondlife:///app/region/{REGION} SLapps // N.B. this is defined to work exactly like the classic secondlife://{REGION} // However, the later syntax cannot support spaces in the region name because @@ -249,6 +262,9 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) return; // this error condition is not recoverable. } + // record that we just entered a new region + newRegionEntry(*regionp); + // After a few attempts, continue login. But keep trying to get the caps: if (mSeedCapAttempts >= mSeedCapMaxAttemptsBeforeLogin && STATE_SEED_GRANTED_WAIT == LLStartUp::getStartupState()) @@ -369,6 +385,9 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle) break; // this error condition is not recoverable. } + // record that we just entered a new region + newRegionEntry(*regionp); + LLSD capabilityNames = LLSD::emptyArray(); buildCapabilityNames(capabilityNames); |