summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llappdelegate-objc.mm43
-rw-r--r--indra/newview/llappviewermacosx-for-objc.h21
-rw-r--r--indra/newview/llappviewermacosx.cpp45
-rw-r--r--indra/newview/llviewerregion.cpp19
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);