From c5f618d096f05bdff91a5d384c46e26840f5a771 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 17 May 2018 06:53:42 -0400
Subject: [PATCH] SL-821: Move Windows BugSplat engagement from llcommon to
 newview.

Use WSTRINGIZE(), LL_TO_WSTRING(), wstringize() to produce required wide
strings. Use a lambda for callback that sends log file; use LLDir, if set, to
find the log file.

Introduce BUGSPLAT CMake variable to allow suppressing BugSplat.
Make BUGSPLAT CMake variable set LL_BUGSPLAT for C++ compilations.

Set viewer version macros on llappviewerwin32.cpp, llappviewerlinux.cpp and
llappdelegate-objc.mm -- because BugSplat needs the viewer version data, and
because the macOS BugSplat hook is engaged in an Objective-C++ function we
override in the app delegate.
---
 indra/cmake/CMakeLists.txt         |  1 +
 indra/cmake/bugsplat.cmake         | 46 ++++++++++++++---------
 indra/llcommon/CMakeLists.txt      | 10 +----
 indra/llcommon/llapp.cpp           | 60 ++----------------------------
 indra/llcommon/llapp.h             | 10 +----
 indra/newview/CMakeLists.txt       | 23 +++++++++++-
 indra/newview/llappviewerwin32.cpp | 49 ++++++++++++++++++++++--
 7 files changed, 101 insertions(+), 98 deletions(-)

diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 4a3ebe4835b..84e1c5d6fde 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -12,6 +12,7 @@ set(cmake_SOURCE_FILES
     Audio.cmake
     BerkeleyDB.cmake
     Boost.cmake
+    bugsplat.cmake
     BuildVersion.cmake
     CEFPlugin.cmake
     CEFPlugin.cmake
diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake
index e9939799029..a7f4194905b 100644
--- a/indra/cmake/bugsplat.cmake
+++ b/indra/cmake/bugsplat.cmake
@@ -1,20 +1,30 @@
-include(Prebuilt)
+# BUGSPLAT can be set when launching the make using the argument -DBUGSPLAT:BOOL=ON
+# When building using proprietary binaries though (i.e. having access to LL private servers),
+# we always build with BUGSPLAT.
+# Open source devs should use the -DBUGSPLAT:BOOL=ON then if they want to
+# build with BugSplat, whether they are using USESYSTEMLIBS or not.
+if (INSTALL_PROPRIETARY)
+  set(BUGSPLAT ON CACHE BOOL "Using BugSplat crash reporting library.")
+endif (INSTALL_PROPRIETARY)
 
-set(BUGSPLAT_FIND_QUIETLY ON)
-set(BUGSPLAT_FIND_REQUIRED ON)
+if (BUGSPLAT)
+  if (USESYSTEMLIBS)
+    set(BUGSPLAT_FIND_QUIETLY ON)
+    set(BUGSPLAT_FIND_REQUIRED ON)
+    include(FindBUGSPLAT)
+  else (USESYSTEMLIBS)
+    include(Prebuilt)
+    use_prebuilt_binary(bugsplat)
+    if (WINDOWS)
+      set(BUGSPLAT_LIBRARIES 
+        ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib
+        )
+    elseif (DARWIN)
+      find_library(BUGSPLAT_LIBRARIES BugsplatMac
+        PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
+    else (WINDOWS)
 
-if (USESYSTEMLIBS)
-  include(FindBUGSPLAT)
-else (USESYSTEMLIBS)
-  use_prebuilt_binary(bugsplat)
-  if (WINDOWS)
-    set(BUGSPLAT_LIBRARIES 
-      ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib
-      )
-  elseif (DARWIN)
-
-  else (WINDOWS)
-
-  endif (WINDOWS)
-  set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
-endif (USESYSTEMLIBS)
+    endif (WINDOWS)
+    set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
+  endif (USESYSTEMLIBS)
+endif (BUGSPLAT)
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 4eba1d54516..d9eb13d65a6 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -13,7 +13,6 @@ include(GoogleBreakpad)
 include(Copy3rdPartyLibs)
 include(ZLIB)
 include(URIPARSER)
-include(BuildVersion)
 
 include_directories(
     ${EXPAT_INCLUDE_DIRS}
@@ -254,14 +253,7 @@ set(llcommon_HEADER_FILES
     )
 
 set_source_files_properties(${llcommon_HEADER_FILES}
-                            PROPERTIES HEADER_FILE_ONLY TRUE
-                            )
-
-# bring in version information for BugSplat crash reporting
-set_source_files_properties(${llcommon_SOURCE_FILES}
-                            PROPERTIES
-                            COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" # see BuildVersion.cmake
-                            )
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
 
 list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
 
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 3e652dbdb51..6cc9e804d4a 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -49,20 +49,6 @@
 #include "google_breakpad/exception_handler.h"
 #include "stringize.h"
 #include "llcleanup.h"
-#include "BugSplat.h"
-
-// TESTING ONLY - REMOVE FOR PRODUCTION
-// (Want to only invoke BugSplat crash reporting in the same way we did for Breakpad - for Release viewers
-// but need to test here in a ReleaseWithDebugInfo environment)
-#if BUGSPLAT_ENABLED
-#define LL_SEND_CRASH_REPORTS 1
-#endif
-
-// BugSplat crash reporting tool - http://bugsplat.com
-#if BUGSPLAT_ENABLED
-bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2);
-MiniDmpSender *gBugSplatSender;
-#endif
 
 //
 // Signal handling
@@ -399,26 +385,6 @@ void EnableCrashingOnCrashes()
 }
 #endif
 
-#if BUGSPLAT_ENABLED
-bool BugSplatExceptionCallback(unsigned int nCode, void* lpVal1, void* lpVal2)
-{
-	switch (nCode)
-	{
-		case MDSCB_EXCEPTIONCODE:
-		{
-			// send the main viewer log file (Clearly a temporary hack since we don't have access to the gDir*** set of functions in newview
-			const std::string appdata = std::string(getenv("APPDATA"));
-			const std::string logfile = appdata + "\\SecondLife\\logs\\Secondlife.log";
-			const std::wstring wide_logfile(logfile.begin(), logfile.end());
-			gBugSplatSender->sendAdditionalFile((const __wchar_t *)wide_logfile.c_str());
-		}
-		break;
-	}
-
-	return false;
-}
-#endif
-
 void LLApp::setupErrorHandling(bool second_instance)
 {
 	// Error handling is done by starting up an error handling thread, which just sleeps and
@@ -427,25 +393,6 @@ void LLApp::setupErrorHandling(bool second_instance)
 #if LL_WINDOWS
 
 #if LL_SEND_CRASH_REPORTS
-
-#if BUGSPLAT_ENABLED
-	// TODOCP: populate these fields correctly
-	static const wchar_t *bugdb_name = L"second_life_callum_test";
-
-	// build (painfully) the app/channel name
-	#define stringize_inner(x) L#x
-	#define stringize_outer(x) stringize_inner(x)
-	std::wstring app_name(stringize_outer(LL_VIEWER_CHANNEL));
-
-	// build in real app version now we leveraged CMake to build in BuildVersion.cmake into LLCommon
-	wchar_t version_string[MAX_STRING];
-	wsprintf(version_string, L"%d.%d.%d.%d", LL_VIEWER_VERSION_MAJOR, LL_VIEWER_VERSION_MINOR, LL_VIEWER_VERSION_PATCH, LL_VIEWER_VERSION_BUILD);
-
-	gBugSplatSender = new MiniDmpSender((const __wchar_t *)bugdb_name, (const __wchar_t *)app_name.c_str(), (const __wchar_t *)version_string, NULL);
-
-	gBugSplatSender->setCallback(BugSplatExceptionCallback);
-#else
-
 	EnableCrashingOnCrashes();
 
 	// This sets a callback to handle w32 signals to the console window.
@@ -507,9 +454,8 @@ void LLApp::setupErrorHandling(bool second_instance)
 			mExceptionHandler->set_handle_debug_exceptions(true);
 		}
 	}
-#endif  // BUGSPLAT_ENABLED
-#endif	// LL_SEND_CRASH_REPORTS
-#else	// not LL_WINDOWS
+#endif
+#else
 	//
 	// Start up signal handling.
 	//
@@ -570,7 +516,7 @@ void LLApp::setupErrorHandling(bool second_instance)
 	}
 #endif
 
-#endif // LL_WINDOWS
+#endif
 	startErrorThread();
 }
 
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 5a4b7f13df5..acd829d8649 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -30,7 +30,6 @@
 #include <map>
 #include "llrun.h"
 #include "llsd.h"
-
 // Forward declarations
 template <typename Type> class LLAtomic32;
 typedef LLAtomic32<U32> LLAtomicU32;
@@ -40,14 +39,6 @@ class LLLiveFile;
 #include <signal.h>
 #endif
 
-// first version of Bugsplat (http://bugsplat.com) crash reporting tool
-// is only supported on Windows - macOS to follow.
-#define BUGSPLAT_ENABLED LL_WINDOWS
-
-#if BUGSPLAT_ENABLED
-class __declspec(dllexport) MiniDmpSender;
-#endif
-
 typedef void (*LLAppErrorHandler)();
 
 #if !LL_WINDOWS
@@ -325,6 +316,7 @@ class LL_COMMON_API LLApp
 	
 	google_breakpad::ExceptionHandler * mExceptionHandler;
 
+
 #if !LL_WINDOWS
 	friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
 #endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1fd0af0558b..2592b532c44 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1354,6 +1354,11 @@ if (DARWIN)
 
   # This should be compiled with the viewer.
   LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm)
+  set_source_files_properties(
+    llappdelegate-objc.mm
+    PROPERTIES
+    COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
+    )
 
   find_library(AGL_LIBRARY AGL)
   find_library(APPKIT_LIBRARY AppKit)
@@ -1366,6 +1371,7 @@ if (DARWIN)
     ${AGL_LIBRARY}
     ${IOKIT_LIBRARY}
     ${COREAUDIO_LIBRARY}
+    ${BUGSPLAT_LIBRARIES}
     )
 
   # Add resource files to the project.
@@ -1393,6 +1399,11 @@ endif (DARWIN)
 
 if (LINUX)
     LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp)
+    set_source_files_properties(
+      llappviewerlinux.cpp
+      PROPERTIES
+      COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
+      )
     LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp)
     SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
 
@@ -1409,6 +1420,11 @@ if (WINDOWS)
          llappviewerwin32.cpp
          llwindebug.cpp
          )
+    set_source_files_properties(
+      llappviewerwin32.cpp
+      PROPERTIES
+      COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
+      )
 
     list(APPEND viewer_HEADER_FILES
          llappviewerwin32.h
@@ -1692,6 +1708,11 @@ if (SDL_FOUND)
     )
 endif (SDL_FOUND)
 
+if (BUGSPLAT)
+  set_property(TARGET ${VIEWER_BINARY_NAME}
+    PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT")
+endif (BUGSPLAT)
+
 # add package files
 file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
      ${CMAKE_CURRENT_SOURCE_DIR}/../viewer_components/*.py)
@@ -1790,7 +1811,7 @@ if (WINDOWS)
            ${SHARED_LIB_STAGING_DIR}/Debug/fmodexL.dll
           )
     endif (FMODEX)
-    
+
     add_custom_command(
       OUTPUT  ${CMAKE_CFG_INTDIR}/copy_touched.bat
       COMMAND ${PYTHON_EXECUTABLE}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 48b3a1c485a..8a014c55d70 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -66,8 +66,18 @@
 #endif
 
 #include "stringize.h"
+#include "lldir.h"
 
 #include <exception>
+
+// Bugsplat (http://bugsplat.com) crash reporting tool
+#ifdef LL_BUGSPLAT
+#include "BugSplat.h"
+
+// FIXME: need a production BugSplat database name
+static const wchar_t *bugdb_name = L"second_life_callum_test";
+#endif
+
 namespace
 {
     void (*gOldTerminateHandler)() = NULL;
@@ -495,15 +505,46 @@ bool LLAppViewerWin32::init()
 	LLWinDebug::instance();
 #endif
 
-#if LL_WINDOWS
 #if LL_SEND_CRASH_REPORTS
-
+#if ! defined(LL_BUGSPLAT)
 
 	LLAppViewer* pApp = LLAppViewer::instance();
 	pApp->initCrashReporting();
 
-#endif
-#endif
+#else // LL_BUGSPLAT
+
+	std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' <<
+										   LL_VIEWER_VERSION_MINOR << '.' <<
+										   LL_VIEWER_VERSION_PATCH << '.' <<
+										   LL_VIEWER_VERSION_BUILD));
+
+	auto sender = new MiniDmpSender(
+		bugdb_name, LL_TO_WSTRING(LL_VIEWER_CHANNEL), version_string.c_str(), nullptr);
+	sender->setCallback(
+		[sender](unsigned int nCode, void* lpVal1, void* lpVal2)
+		{
+			// If we haven't yet initialized LLDir, don't bother trying to
+			// find our log file.
+			// Alternatively -- if we might encounter trouble trying to query
+			// LLDir during crash cleanup -- consider making gDirUtilp an
+			// LLPounceable, and attach a callback that stores the pathname to
+			// the log file here.
+			if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp)
+			{
+				// send the main viewer log file
+				// widen to wstring, then pass c_str()
+				sender->sendAdditionalFile(
+					wstringize(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str());
+			}
+
+			return false;
+		});
+
+	LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
+			   << version_string << ')' << LL_ENDL;
+
+#endif // LL_BUGSPLAT
+#endif // LL_SEND_CRASH_REPORTS
 
 	bool success = LLAppViewer::init();
 
-- 
GitLab