From 719edddf0498752a0295502d62710823d1a72cc7 Mon Sep 17 00:00:00 2001
From: "Andrew A. de Laix" <alain@lindenlab.com>
Date: Fri, 21 May 2010 09:38:29 -0700
Subject: [PATCH] Switch Darwin to use breakpad minidump rather than os
 generated crash stack.

---
 indra/llcommon/CMakeLists.txt         |  1 +
 indra/llcommon/llapp.cpp              | 51 ++++++++++++++++++++++++++-
 indra/llcommon/llapp.h                | 11 ++++--
 indra/llcrashlogger/llcrashlogger.cpp | 21 +++++++++++
 indra/newview/llappviewer.cpp         |  2 ++
 install.xml                           | 11 ++++--
 6 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 3c689930b8b..051e198e750 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -259,6 +259,7 @@ endif(LLCOMMON_LINK_SHARED)
 
 target_link_libraries(
     llcommon
+    exception_handler
     ${APRUTIL_LIBRARIES}
     ${APR_LIBRARIES}
     ${EXPAT_LIBRARIES}
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 6b2d1b7c201..e766563c6f8 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -56,6 +56,11 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
 # 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 darwin_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;
@@ -123,7 +128,10 @@ void LLApp::commonCtor()
 
 	// Set the application to this instance.
 	sApplication = this;
-
+	
+	mExceptionHandler = 0;
+	
+	memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH);
 }
 
 LLApp::LLApp(LLErrorThread *error_thread) :
@@ -152,6 +160,8 @@ LLApp::~LLApp()
 		delete mThreadErrorp;
 		mThreadErrorp = NULL;
 	}
+	
+	if(mExceptionHandler != 0) delete mExceptionHandler;
 
 	LLCommon::cleanupClass();
 }
@@ -285,6 +295,15 @@ void LLApp::setupErrorHandling()
 
 	setup_signals();
 
+	
+#ifdef LL_DARWIN
+	// Add google breakpad exception handler configured for Darwin.
+	if(mExceptionHandler == 0)
+	{
+		std::string dumpPath = "/tmp/";
+		mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &darwin_post_minidump_callback, 0, true);
+	}
+#endif
 #endif
 
 	startErrorThread();
@@ -587,6 +606,7 @@ void setup_signals()
 
 	// Asynchronous signals that result in core
 	sigaction(SIGQUIT, &act, NULL);
+	
 }
 
 void clear_signals()
@@ -766,3 +786,32 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 }
 
 #endif // !WINDOWS
+
+bool darwin_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()->minidump_path;
+	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
+	strncpy(path, dump_dir, remaining);
+	remaining -= dirPathLength;
+	path += dirPathLength;
+	strncpy(path, minidump_id, remaining);
+	remaining -= idLength;
+	path += idLength;
+	strncpy(path, ".dmp", remaining);
+	
+	llinfos << "generated minidump: " << LLApp::instance()->minidump_path << llendl;
+	LLApp::runErrorHandler();
+	return true;
+}
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index e5b8edf9c39..cd175322034 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -38,6 +38,8 @@
 #include "llsd.h"
 #include "lloptioninterface.h"
 
+#include "exception_handler.h"
+
 // Forward declarations
 template <typename Type> class LLAtomic32;
 typedef LLAtomic32<U32> LLAtomicU32;
@@ -228,6 +230,8 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 
 	void setErrorHandler(LLAppErrorHandler handler);
 	void setSyncErrorHandler(LLAppErrorHandler handler);
+	static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
+	static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
 	//@}
 
 #if !LL_WINDOWS
@@ -265,6 +269,9 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 	typedef std::map<std::string, std::string> string_map;
 	string_map mOptionMap;	// Contains all command-line options and arguments in a map
 
+	// Contains the path to minidump file after a crash.
+	static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
+	char minidump_path[MAX_MINDUMP_PATH_LENGTH];
 protected:
 
 	static void setStatus(EAppStatus status);		// Use this to change the application status.
@@ -286,8 +293,6 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 private:
 	void startErrorThread();
 	
-	static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
-	static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
 
 	// *NOTE: On Windows, we need a routine to reset the structured
 	// exception handler when some evil driver has taken it over for
@@ -315,6 +320,8 @@ class LL_COMMON_API LLApp : public LLOptionInterface
 private:
 	// the static application instance if it was created.
 	static LLApp* sApplication;
+	
+	google_breakpad::ExceptionHandler * mExceptionHandler;
 
 
 #if !LL_WINDOWS
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index c1022c1195e..8f5aa5ab2da 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -274,6 +274,27 @@ void LLCrashLogger::gatherFiles()
 
 		mCrashInfo[(*itr).first] = rawstr_to_utf8(crash_info);
 	}
+	
+	// Add minidump as binary.
+	std::string minidump_path = mDebugLog["MinidumpPath"];
+	if(minidump_path != "")
+	{
+		std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary);
+		if(minidump_stream.is_open())
+		{
+			minidump_stream.seekg(0, std::ios::end);
+			size_t length = minidump_stream.tellg();
+			minidump_stream.seekg(0, std::ios::beg);
+			
+			LLSD::Binary data;
+			data.resize(length);
+			
+			minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length);
+			minidump_stream.close();
+			
+			mCrashInfo["Minidump"] = data;
+		}
+	}
 }
 
 LLSD LLCrashLogger::constructPostData()
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f7f7cb599e9..56486c788bd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2587,6 +2587,8 @@ void LLAppViewer::handleViewerCrash()
 	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
 	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
 
+	if(pApp->minidump_path[0] != 0) gDebugInfo["MinidumpPath"] = pApp->minidump_path;
+	
 	if(gLogoutInProgress)
 	{
 		gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
diff --git a/install.xml b/install.xml
index 1ac6f7d918f..e59634fcb21 100644
--- a/install.xml
+++ b/install.xml
@@ -595,10 +595,17 @@
         <map>
           <key>darwin</key>
           <map>
+            <key>i386</key>
+            <map>
+              <key>md5sum</key>
+              <string>84139a373314b85e0c27e13a5263dcc6</string>
+              <key>url</key>
+              <uri> http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20100519.tar.bz2</uri>
+            </map>
             <key>md5sum</key>
-            <string>34bb9d8dd8247fdbe238cf96813f333b</string>
+            <string>c7b20b28a256a74fb646bd2ddbc3ec32</string>
             <key>url</key>
-            <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20100517.tar.bz2</uri>
+            <uri> http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20100519a.tar.bz2</uri>
           </map>
           <key>windows</key>
           <map>
-- 
GitLab