From f648758c2a3da2dd03c8f57e98598c085b2030a6 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 16 Jan 2019 11:05:55 -0500
Subject: SL-10297: Modify LL_ERRS and other deliberate crashes to avoid a
 common stack frame

---
 indra/llcommon/llerror.cpp            | 51 ++++++--------------
 indra/llcommon/llerror.h              | 24 ++++++++--
 indra/llcommon/llerrorcontrol.h       | 36 ++------------
 indra/llcommon/llleap.cpp             | 12 ++---
 indra/llcommon/llsingleton.cpp        | 10 +---
 indra/llcommon/tests/llerror_test.cpp |  2 +-
 indra/llcommon/tests/wrapllerrs.h     | 10 ++--
 indra/newview/llappviewer.cpp         | 89 ++++++-----------------------------
 indra/newview/llwatchdog.cpp          | 18 ++-----
 indra/newview/llwatchdog.h            |  6 +--
 indra/test/test.cpp                   |  6 +--
 11 files changed, 70 insertions(+), 194 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 335a0995fe..0ddce353f1 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -683,7 +683,6 @@ namespace
 		LLError::setDefaultLevel(LLError::LEVEL_INFO);
         LLError::setAlwaysFlush(true);
         LLError::setEnabledLogTypesMask(0xFFFFFFFF);
-		LLError::setFatalFunction(LLError::crashAndLoop);
 		LLError::setTimeFunction(LLError::utcTime);
 
 		// log_to_stderr is only false in the unit and integration tests to keep builds quieter
@@ -719,16 +718,16 @@ namespace LLError
 		commonInit(user_dir, app_dir, log_to_stderr);
 	}
 
-	void setFatalFunction(const FatalFunction& f)
+	void overrideCrashOnError(const FatalFunction& fatal_function)
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-		s->mCrashFunction = f;
+		s->mCrashFunction = fatal_function;
 	}
 
-	FatalFunction getFatalFunction()
+	void restoreCrashOnError()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-		return s->mCrashFunction;
+		s->mCrashFunction = NULL;
 	}
 
 	std::string getFatalMessage()
@@ -1306,12 +1305,12 @@ namespace LLError
 		return ;
 	}
 
-	void Log::flush(std::ostringstream* out, const CallSite& site)
+	bool Log::flush(std::ostringstream* out, const CallSite& site)
 	{
 		LLMutexTrylock lock(&gLogMutex,5);
 		if (!lock.isLocked())
 		{
-			return;
+			return true;
 		}
 
 		// If we hit a logging request very late during shutdown processing,
@@ -1319,7 +1318,7 @@ namespace LLError
 		// DO NOT resurrect them.
 		if (Settings::wasDeleted() || Globals::wasDeleted())
 		{
-			return;
+			return true;
 		}
 
 		Globals* g = Globals::getInstance();
@@ -1353,7 +1352,7 @@ namespace LLError
 				} 
 				else
 				{
-					return;
+					return true;
 				}
 			}
 			else 
@@ -1370,11 +1369,14 @@ namespace LLError
 		if (site.mLevel == LEVEL_ERROR)
 		{
 			g->mFatalMessage = message;
-			if (s->mCrashFunction)
-			{
-				s->mCrashFunction(message);
-			}
+            if (s->mCrashFunction)
+            {
+                s->mCrashFunction(message);
+                return false;
+            }
 		}
+
+        return true;
 	}
 }
 
@@ -1437,29 +1439,6 @@ namespace LLError
 		return s->mShouldLogCallCounter;
 	}
 
-#if LL_WINDOWS
-		// VC80 was optimizing the error away.
-		#pragma optimize("", off)
-#endif
-	void crashAndLoop(const std::string& message)
-	{
-		// Now, we go kaboom!
-		int* make_me_crash = NULL;
-
-		*make_me_crash = 0;
-
-		while(true)
-		{
-			// Loop forever, in case the crash didn't work?
-		}
-		
-		// this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever.
-		exit(EXIT_FAILURE);
-	}
-#if LL_WINDOWS
-		#pragma optimize("", on)
-#endif
-
 	std::string utcTime()
 	{
 		time_t now = time(NULL);
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 0a78229555..cbade88f61 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -199,8 +199,12 @@ namespace LLError
 	public:
 		static bool shouldLog(CallSite&);
 		static std::ostringstream* out();
+
 		static void flush(std::ostringstream* out, char* message);
-		static void flush(std::ostringstream*, const CallSite&);
+
+        // returns false iff there is a fatal crash override in effect
+		static bool flush(std::ostringstream*, const CallSite&);
+
 		static std::string demangle(const char* mangled);
 	};
 	
@@ -367,10 +371,20 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 #define LL_NEWLINE '\n'
 
-#define LL_ENDL                               \
-			LLError::End();                   \
-			LLError::Log::flush(_out, _site); \
-		}                                     \
+// Use this only in LL_ERRS or in a place that LL_ERRS may not be used
+#define LLERROR_CRASH         \
+{                             \
+    int* make_me_crash = NULL;\
+    *make_me_crash = 0;       \
+    exit(*make_me_crash);     \
+}
+
+#define LL_ENDL                                          \
+			LLError::End();                              \
+            if (LLError::Log::flush(_out, _site)         \
+                && _site.mLevel == LLError::LEVEL_ERROR) \
+                LLERROR_CRASH                            \
+        }                                                \
 	} while(0)
 
 // NEW Macros for debugging, allow the passing of a string tag
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 276d22fc36..7ca6ddb737 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -92,41 +92,13 @@ namespace LLError
 	/*
 		Control functions.
 	*/
-
 	typedef boost::function<void(const std::string&)> FatalFunction;
-	LL_COMMON_API void crashAndLoop(const std::string& message);
-		// Default fatal function: access null pointer and loops forever
-
-	LL_COMMON_API void setFatalFunction(const FatalFunction&);
-		// The fatal function will be called when an message of LEVEL_ERROR
-		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
-		// (by, for example, setting a class level to LEVEL_NONE), will keep
-		// the that message from causing the fatal funciton to be invoked.
-
-	LL_COMMON_API FatalFunction getFatalFunction();
-		// Retrieve the previously-set FatalFunction
 
+    LL_COMMON_API void overrideCrashOnError(const FatalFunction&);
+    LL_COMMON_API void restoreCrashOnError();
+    
 	LL_COMMON_API std::string getFatalMessage();
-		// Retrieve the message last passed to FatalFunction, if any
-
-	/// temporarily override the FatalFunction for the duration of a
-	/// particular scope, e.g. for unit tests
-	class LL_COMMON_API OverrideFatalFunction
-	{
-	public:
-		OverrideFatalFunction(const FatalFunction& func):
-			mPrev(getFatalFunction())
-		{
-			setFatalFunction(func);
-		}
-		~OverrideFatalFunction()
-		{
-			setFatalFunction(mPrev);
-		}
-
-	private:
-		FatalFunction mPrev;
-	};
+		// Retrieve the message last passed to LL_ERRS, if any
 
 	typedef std::string (*TimeFunction)();
 	LL_COMMON_API std::string utcTime();
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index cf8f8cc6a5..f7bfa36bb5 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -59,7 +59,6 @@ public:
         // pump name -- so it should NOT need tweaking for uniqueness.
         mReplyPump(LLUUID::generateNewID().asString()),
         mExpect(0),
-        mPrevFatalFunction(LLError::getFatalFunction()),
         // Instantiate a distinct LLLeapListener for this plugin. (Every
         // plugin will want its own collection of managed listeners, etc.)
         // Pass it a callback to our connect() method, so it can send events
@@ -146,7 +145,7 @@ public:
             .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
 
         // For our lifespan, intercept any LL_ERRS so we can notify plugin
-        LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1));
+        LLError::overrideCrashOnError(boost::bind(&LLLeapImpl::fatalFunction, this, _1));
 
         // Send child a preliminary event reporting our own reply-pump name --
         // which would otherwise be pretty tricky to guess!
@@ -162,8 +161,8 @@ public:
     virtual ~LLLeapImpl()
     {
         LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
-        // Restore original FatalFunction
-        LLError::setFatalFunction(mPrevFatalFunction);
+        // Restore original fatal crash behavior for LL_ERRS
+        LLError::restoreCrashOnError();
     }
 
     // Listener for failed launch attempt
@@ -397,8 +396,8 @@ public:
             mainloop.post(nop);
         }
 
-        // forward the call to the previous FatalFunction
-        mPrevFatalFunction(error);
+        // go ahead and do the crash that LLError would have done
+        LLERROR_CRASH
     }
 
 private:
@@ -421,7 +420,6 @@ private:
         mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
     boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
     LLProcess::ReadPipe::size_type mExpect;
-    LLError::FatalFunction mPrevFatalFunction;
     boost::scoped_ptr<LLLeapListener> mListener;
 };
 
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index c45c144570..6f254ef670 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -461,15 +461,7 @@ void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, co
     // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
     std::ostringstream out;
     out << p1 << p2 << p3 << p4;
-    auto crash = LLError::getFatalFunction();
-    if (crash)
-    {
-        crash(out.str());
-    }
-    else
-    {
-        LLError::crashAndLoop(out.str());
-    }
+    LLERROR_CRASH;
 }
 
 std::string LLSingletonBase::demangle(const char* mangled)
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 8e1f4c14ac..2f8923d2de 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -120,7 +120,7 @@ namespace tut
 
 			mPriorErrorSettings = LLError::saveAndResetSettings();
 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
-			LLError::setFatalFunction(fatalCall);
+			LLError::overrideCrashOnError(fatalCall);
 			LLError::addRecorder(mRecorder);
 		}
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index b07d5afbd8..b280271476 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -54,17 +54,15 @@ struct WrapLLErrs
         // Resetting Settings discards the default Recorder that writes to
         // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
         // console output of successful tests, potentially confusing things.
-        mPriorErrorSettings(LLError::saveAndResetSettings()),
-        // Save shutdown function called by LL_ERRS
-        mPriorFatal(LLError::getFatalFunction())
+        mPriorErrorSettings(LLError::saveAndResetSettings())
     {
         // Make LL_ERRS call our own operator() method
-        LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1));
+        LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1));
     }
 
     ~WrapLLErrs()
     {
-        LLError::setFatalFunction(mPriorFatal);
+        LLError::restoreCrashOnError();
         LLError::restoreSettings(mPriorErrorSettings);
     }
 
@@ -203,7 +201,7 @@ public:
         mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new CaptureLogRecorder())
     {
-        LLError::setFatalFunction(wouldHaveCrashed);
+        LLError::overrideCrashOnError(wouldHaveCrashed);
         LLError::setDefaultLevel(level);
         LLError::addRecorder(mRecorder);
     }
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a33e978c0a..e6ba3e4f7c 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -751,17 +751,6 @@ public:
 	}
 };
 
-namespace {
-// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide
-// this little helper function.
-void fast_exit(int rc)
-{
-	_exit(rc);
-}
-
-
-}
-
 
 bool LLAppViewer::init()
 {
@@ -801,19 +790,6 @@ bool LLAppViewer::init()
 	initMaxHeapSize() ;
 	LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
 
-
-	// Although initLoggingAndGetLastDuration() is the right place to mess with
-	// setFatalFunction(), we can't query gSavedSettings until after
-	// initConfiguration().
-	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
-	if (rc >= 0)
-	{
-		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
-		// fast_exit() rather than exit() because normal cleanup depends too
-		// much on successful startup!
-		LLError::setFatalFunction(boost::bind(fast_exit, rc));
-	}
-
     mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
 
 	// Initialize the non-LLCurl libcurl library.  Should be called
@@ -2120,28 +2096,9 @@ bool LLAppViewer::cleanup()
 	return true;
 }
 
-// A callback for LL_ERRS() to call during the watchdog error.
-void watchdog_llerrs_callback(const std::string &error_string)
-{
-	gLLErrorActivated = true;
-
 	gDebugInfo["FatalMessage"] = error_string;
 	LLAppViewer::instance()->writeDebugInfo();
 
-#ifdef LL_WINDOWS
-	RaiseException(0,0,0,0);
-#else
-	raise(SIGQUIT);
-#endif
-}
-
-// A callback for the watchdog to call.
-void watchdog_killer_callback()
-{
-	LLError::setFatalFunction(watchdog_llerrs_callback);
-	LL_ERRS() << "Watchdog killer event" << LL_ENDL;
-}
-
 bool LLAppViewer::initThreads()
 {
 	static const bool enable_threads = true;
@@ -2176,24 +2133,6 @@ bool LLAppViewer::initThreads()
 	return true;
 }
 
-void errorCallback(const std::string &error_string)
-{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
-#endif
-
-	//Set the ErrorActivated global so we know to create a marker file
-	gLLErrorActivated = true;
-
-	gDebugInfo["FatalMessage"] = error_string;
-	// We're not already crashing -- we simply *intend* to crash. Since we
-	// haven't actually trashed anything yet, we can afford to write the whole
-	// static info file.
-	LLAppViewer::instance()->writeDebugInfo();
-
-	LLError::crashAndLoop(error_string);
-}
-
 void LLAppViewer::initLoggingAndGetLastDuration()
 {
 	//
@@ -2202,8 +2141,6 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
                                 ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
                                 );
-	LLError::setFatalFunction(errorCallback);
-	//LLError::setTimeFunction(getRuntime);
 
 	// Remove the last ".old" log file.
 	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
@@ -2952,6 +2889,7 @@ bool LLAppViewer::initWindow()
 	// Need to load feature table before cheking to start watchdog.
 	bool use_watchdog = false;
 	int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
+
 	if (watchdog_enabled_setting == -1)
 	{
 		use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
@@ -2962,11 +2900,16 @@ bool LLAppViewer::initWindow()
 		use_watchdog = bool(watchdog_enabled_setting);
 	}
 
+    LL_INFOS("AppInit") << "watchdog"
+                        << (use_watchdog ? " " : " NOT ")
+                        << "enabled"
+                        << " (setting = " << watchdog_enabled_setting << ")"
+                        << LL_ENDL;
+
 	if (use_watchdog)
 	{
-		LLWatchdog::getInstance()->init(watchdog_killer_callback);
+		LLWatchdog::getInstance()->init();
 	}
-	LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;
 
 	LLNotificationsUI::LLNotificationManager::getInstance();
 
@@ -3409,12 +3352,10 @@ void LLAppViewer::writeSystemInfo()
 	gDebugInfo["MainloopThreadID"] = (S32)thread_id;
 #endif
 
-	// "CrashNotHandled" is set here, while things are running well,
-	// in case of a freeze. If there is a freeze, the crash logger will be launched
-	// and can read this value from the debug_info.log.
-	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
-	// then the value of "CrashNotHandled" will be set to true.
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
+	// "CrashNotHandled" is obsolete; it used (not very successsfully)
+    // to try to distinguish crashes from freezes
+	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
+    gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
 
 	// Insert crash host url (url to post crash log to) if configured. This insures
 	// that the crash report will go to the proper location in the case of a
@@ -3567,10 +3508,6 @@ void LLAppViewer::handleViewerCrash()
 		gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
 	}
 
-	// The crash is being handled here so set this value to false.
-	// Otherwise the crash logger will think this crash was a freeze.
-	gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
-
 	//Write out the crash status file
 	//Use marker file style setup, as that's the simplest, especially since
 	//we're already in a crash situation
@@ -3642,6 +3579,8 @@ void LLAppViewer::handleViewerCrash()
 
 	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
 
+	gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage();
+
 	// Close the debug file
 	pApp->writeDebugInfo(false);  //false answers the isStatic question with the least overhead.
 }
diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp
index dd6c77ca7d..2f3e5db84f 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/newview/llwatchdog.cpp
@@ -31,15 +31,6 @@
 
 const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000;
 
-void default_killer_callback()
-{
-#ifdef LL_WINDOWS
-	RaiseException(0,0,0,0);
-#else
-	raise(SIGQUIT);
-#endif
-}
-
 // This class runs the watchdog timing thread.
 class LLWatchdogTimerThread : public LLThread
 {
@@ -157,8 +148,7 @@ void LLWatchdogTimeout::ping(const std::string& state)
 LLWatchdog::LLWatchdog() :
 	mSuspectsAccessMutex(),
 	mTimer(NULL),
-	mLastClockCount(0),
-	mKillerCallback(&default_killer_callback)
+	mLastClockCount(0)
 {
 }
 
@@ -180,9 +170,8 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
 	unlockThread();
 }
 
-void LLWatchdog::init(killer_event_callback func)
+void LLWatchdog::init()
 {
-	mKillerCallback = func;
 	if(!mSuspectsAccessMutex && !mTimer)
 	{
 		mSuspectsAccessMutex = new LLMutex();
@@ -249,8 +238,7 @@ void LLWatchdog::run()
 				mTimer->stop();
 			}
 
-			LL_INFOS() << "Watchdog detected error:" << LL_ENDL;
-			mKillerCallback();
+            LL_ERRS() << "Watchdog timer expired; assuming viewer is hung and crashing" << LL_ENDL;
 		}
 	}
 
diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h
index 9a6624258e..ce5cf748f4 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/newview/llwatchdog.h
@@ -83,9 +83,7 @@ public:
 	void add(LLWatchdogEntry* e);
 	void remove(LLWatchdogEntry* e);
 
-	typedef boost::function<void (void)> killer_event_callback;
-
-	void init(killer_event_callback func = NULL);
+	void init();
 	void run();
 	void cleanup();
     
@@ -98,8 +96,6 @@ private:
 	LLMutex* mSuspectsAccessMutex;
 	LLWatchdogTimerThread* mTimer;
 	U64 mLastClockCount;
-
-	killer_event_callback mKillerCallback;
 };
 
 #endif // LL_LLTHREADWATCHDOG_H
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index b14c2eb255..125de72b79 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -146,7 +146,7 @@ public:
 		mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new RecordToTempFile(pool))
 	{
-		LLError::setFatalFunction(wouldHaveCrashed);
+		LLError::overrideCrashOnError(wouldHaveCrashed);
 		LLError::setDefaultLevel(level);
 		LLError::addRecorder(mRecorder);
 	}
@@ -508,7 +508,7 @@ void stream_groups(std::ostream& s, const char* app)
 
 void wouldHaveCrashed(const std::string& message)
 {
-	tut::fail("llerrs message: " + message);
+	tut::fail("fatal error message: " + message);
 }
 
 static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
@@ -532,7 +532,7 @@ int main(int argc, char **argv)
 		LLError::initForApplication(".", ".", false /* do not log to stderr */);
 		LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
 	}	
-	LLError::setFatalFunction(wouldHaveCrashed);
+	LLError::overrideCrashOnError(wouldHaveCrashed);
 	std::string test_app_name(argv[0]);
 	std::string test_log = test_app_name + ".log";
 	LLFile::remove(test_log);
-- 
cgit v1.2.3


From fc90cad4f366c4bb85add832a2fa8137b1f120ff Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 16 Jan 2019 16:42:34 -0500
Subject: change the default crash type from "freeze" to "other"

---
 indra/newview/llappviewer.cpp | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e6ba3e4f7c..1fda07edd6 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3508,6 +3508,10 @@ void LLAppViewer::handleViewerCrash()
 		gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
 	}
 
+	// The crash is being handled here so set this value to false.
+	// Otherwise the crash logger will think this crash was a freeze.
+	gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
+
 	//Write out the crash status file
 	//Use marker file style setup, as that's the simplest, especially since
 	//we're already in a crash situation
@@ -3680,8 +3684,11 @@ void LLAppViewer::processMarkerFiles()
 		{
 			// the file existed, is ours, and matched our version, so we can report on what it says
 			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL;
+#           if LL_BUGSPLAT            
+			gLastExecEvent = LAST_EXEC_OTHER_CRASH;
+#           else
 			gLastExecEvent = LAST_EXEC_FROZE;
-
+#           endif
 		}
 		else
 		{
-- 
cgit v1.2.3


From e409c0492f1b1ce63606c0b693c92cdb36dcc28b Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Sat, 2 Mar 2019 11:58:11 -0500
Subject: convert to an explicit USE_BUGSPLAT switch in cmake, revise LL_ERRS
 approach

---
 indra/CMakeLists.txt               | 10 +++++++
 indra/cmake/Copy3rdPartyLibs.cmake |  4 +--
 indra/cmake/LLAddBuildTest.cmake   | 13 ++++++++-
 indra/cmake/Variables.cmake        |  1 -
 indra/cmake/bugsplat.cmake         | 53 +++++++++++++++++++---------------
 indra/llcommon/CMakeLists.txt      |  9 +++---
 indra/llcommon/llerror.cpp         | 21 +++++++++-----
 indra/llcommon/llerror.h           | 20 +++++++------
 indra/llcommon/llerrorcontrol.h    | 14 +++++++--
 indra/llcommon/llleap.cpp          | 30 +------------------
 indra/llcommon/tests/wrapllerrs.h  |  5 ++--
 indra/llcorehttp/CMakeLists.txt    |  1 +
 indra/llimage/CMakeLists.txt       |  1 +
 indra/llmath/CMakeLists.txt        |  1 +
 indra/newview/CMakeLists.txt       | 36 +++++++++++------------
 indra/newview/llappviewer.cpp      | 59 +++++++++++++++++++++++++++++++++-----
 indra/newview/llwatchdog.cpp       |  8 +++---
 indra/test/CMakeLists.txt          |  6 +++-
 indra/test/test.cpp                | 10 +++----
 19 files changed, 185 insertions(+), 117 deletions(-)

(limited to 'indra')

diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 62a8f3f003..cf6029c4ae 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -13,6 +13,7 @@ project(${ROOT_PROJECT_NAME})
 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
 
 include(Variables)
+include(bugsplat)
 include(BuildVersion)
 
 if (NOT CMAKE_BUILD_TYPE)
@@ -89,6 +90,15 @@ set_property(
     PROPERTY VS_STARTUP_PROJECT secondlife-bin
     )
 
+if (USE_BUGSPLAT)
+    if (BUGSPLAT_DB)
+        message(STATUS "Building with BugSplat; database '${BUGSPLAT_DB}'")
+    else (BUGSPLAT_DB)
+        message(WARNING "Building with BugSplat, but no database name set (BUGSPLAT_DB)")
+    endif (BUGSPLAT_DB)
+else (USE_BUGSPLAT)
+    message(STATUS "Not building with BugSplat")
+endif (USE_BUGSPLAT)
 if (LL_TESTS)
   # Define after the custom targets are created so
   # individual apps can add themselves as dependencies
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index c73a1fdb47..ebb6379aed 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -50,7 +50,7 @@ if(WINDOWS)
 
     # Filenames are different for 32/64 bit BugSplat file and we don't
     # have any control over them so need to branch.
-    if (BUGSPLAT_DB)
+    if (USE_BUGSPLAT)
       if(ADDRESS_SIZE EQUAL 32)
         set(release_files ${release_files} BugSplat.dll)
         set(release_files ${release_files} BugSplatRc.dll)
@@ -60,7 +60,7 @@ if(WINDOWS)
         set(release_files ${release_files} BugSplatRc64.dll)
         set(release_files ${release_files} BsSndRpt64.exe)
       endif(ADDRESS_SIZE EQUAL 32)
-    endif (BUGSPLAT_DB)
+    endif (USE_BUGSPLAT)
 
     if (FMODEX)
 
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index b3f42c1a5e..fa10a9d443 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -2,6 +2,7 @@
 include(00-Common)
 include(LLTestCommand)
 include(GoogleMock)
+include(bugsplat)
 include(Tut)
 
 #*****************************************************************************
@@ -22,7 +23,6 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
   # there is another branch that will conflict heavily with any changes here.
 INCLUDE(GoogleMock)
 
-
   IF(LL_TEST_VERBOSE)
     MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
   ENDIF(LL_TEST_VERBOSE)
@@ -87,6 +87,12 @@ INCLUDE(GoogleMock)
     IF(LL_TEST_VERBOSE)
       MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
     ENDIF(LL_TEST_VERBOSE)
+
+    if (USE_BUGSPLAT)
+      SET_PROPERTY(SOURCE ${${name}_test_SOURCE_FILES}
+          APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
+    endif (USE_BUGSPLAT)
+
     # Headers
     GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
     SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
@@ -223,6 +229,11 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
     SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
   endif(USESYSTEMLIBS)
 
+  if (USE_BUGSPLAT)
+      SET_PROPERTY(SOURCE ${source_files}
+          APPEND PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
+  endif (USE_BUGSPLAT)
+
   # The following was copied to llcorehttp/CMakeLists.txt's texture_load target. 
   # Any changes made here should be replicated there.
   if (WINDOWS)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index a5770c5528..c81b22e572 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -34,7 +34,6 @@ set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable fo
 set(INCREMENTAL_LINK OFF CACHE BOOL "Use incremental linking on win32 builds (enable for faster links on some machines)")
 set(ENABLE_MEDIA_PLUGINS ON CACHE BOOL "Turn off building media plugins if they are imported by third-party library mechanism")
 set(VIEWER_SYMBOL_FILE "" CACHE STRING "Name of tarball into which to place symbol files")
-set(BUGSPLAT_DB "" CACHE STRING "BugSplat database name, if BugSplat crash reporting is desired")
 
 if(LIBS_CLOSED_DIR)
   file(TO_CMAKE_PATH "${LIBS_CLOSED_DIR}" LIBS_CLOSED_DIR)
diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake
index 59644b73ce..749ea05403 100644
--- a/indra/cmake/bugsplat.cmake
+++ b/indra/cmake/bugsplat.cmake
@@ -1,25 +1,32 @@
-# BugSplat is engaged by setting BUGSPLAT_DB to the target BugSplat database
-# name.
-if (BUGSPLAT_DB)
-  if (USESYSTEMLIBS)
-    message(STATUS "Looking for system BugSplat")
-    set(BUGSPLAT_FIND_QUIETLY ON)
-    set(BUGSPLAT_FIND_REQUIRED ON)
-    include(FindBUGSPLAT)
-  else (USESYSTEMLIBS)
-    message(STATUS "Engaging autobuild BugSplat")
-    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 (INSTALL_PROPRIETARY)
+    set(USE_BUGSPLAT ON  CACHE BOOL "Use the BugSplat crash reporting system")
+else (INSTALL_PROPRIETARY)
+    set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system")
+endif (INSTALL_PROPRIETARY)
+
+if (USE_BUGSPLAT)
+    if (NOT 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)
+            message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF")
+        endif (WINDOWS)
+    else (NOT USESYSTEMLIBS)
+        set(BUGSPLAT_FIND_QUIETLY ON)
+        set(BUGSPLAT_FIND_REQUIRED ON)
+        include(FindBUGSPLAT)
+    endif (NOT USESYSTEMLIBS)
+
+    set(BUGSPLAT_DB "" CACHE STRING "BugSplat crash database name")
 
-    endif (WINDOWS)
     set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat)
-  endif (USESYSTEMLIBS)
-endif (BUGSPLAT_DB)
+    set(BUGSPLAT_DEFINE "LL_BUGSPLAT")
+endif (USE_BUGSPLAT)
+
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index af41b9e460..e3afa5eca4 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -5,6 +5,7 @@ project(llcommon)
 
 include(00-Common)
 include(LLCommon)
+include(bugsplat)
 include(Linking)
 include(Boost)
 include(LLSharedLibs)
@@ -257,10 +258,10 @@ set(llcommon_HEADER_FILES
 set_source_files_properties(${llcommon_HEADER_FILES}
                             PROPERTIES HEADER_FILE_ONLY TRUE)
 
-if (BUGSPLAT_DB)
-  set_source_files_properties(llapp.cpp
-    PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT")
-endif (BUGSPLAT_DB)
+if (USE_BUGSPLAT)
+  set_source_files_properties(${llcommon_SOURCE_FILES}
+    PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
+endif (USE_BUGSPLAT)
 
 list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
 
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 0ddce353f1..77d7fe1b24 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -25,6 +25,7 @@
  * $/LicenseInfo$
  */
 
+#define _LLERROR_CPP_
 #include "linden_common.h"
 
 #include "llerror.h"
@@ -724,7 +725,7 @@ namespace LLError
 		s->mCrashFunction = fatal_function;
 	}
 
-	void restoreCrashOnError()
+    void restoreCrashOnError()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		s->mCrashFunction = NULL;
@@ -1310,7 +1311,7 @@ namespace LLError
 		LLMutexTrylock lock(&gLogMutex,5);
 		if (!lock.isLocked())
 		{
-			return true;
+			return false; // because this wasn't logged, it cannot be fatal
 		}
 
 		// If we hit a logging request very late during shutdown processing,
@@ -1318,7 +1319,7 @@ namespace LLError
 		// DO NOT resurrect them.
 		if (Settings::wasDeleted() || Globals::wasDeleted())
 		{
-			return true;
+            return false; // because this wasn't logged, it cannot be fatal
 		}
 
 		Globals* g = Globals::getInstance();
@@ -1352,7 +1353,7 @@ namespace LLError
 				} 
 				else
 				{
-					return true;
+					return false; // because this wasn't logged, it cannot be fatal
 				}
 			}
 			else 
@@ -1372,11 +1373,17 @@ namespace LLError
             if (s->mCrashFunction)
             {
                 s->mCrashFunction(message);
-                return false;
+                return false; // because an override is in effect
+            }
+            else
+            {
+                return true; // calling macro should crash
             }
 		}
-
-        return true;
+        else
+        {
+            return false; // not ERROR, so do not crash
+        }
 	}
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index cbade88f61..07aa5c6f8b 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -202,7 +202,7 @@ namespace LLError
 
 		static void flush(std::ostringstream* out, char* message);
 
-        // returns false iff there is a fatal crash override in effect
+        // returns false iff the calling macro should crash
 		static bool flush(std::ostringstream*, const CallSite&);
 
 		static std::string demangle(const char* mangled);
@@ -371,18 +371,22 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 #define LL_NEWLINE '\n'
 
+#ifdef _LLERROR_CPP_
+volatile int* gCauseCrash = NULL;
+#else
+volatile extern int* gCauseCrash;
+#endif // _LLERROR_CPP_
+
 // Use this only in LL_ERRS or in a place that LL_ERRS may not be used
-#define LLERROR_CRASH         \
-{                             \
-    int* make_me_crash = NULL;\
-    *make_me_crash = 0;       \
-    exit(*make_me_crash);     \
+#define LLERROR_CRASH       \
+{                           \
+    *gCauseCrash = 0;       \
+    exit(*gCauseCrash);     \
 }
 
 #define LL_ENDL                                          \
 			LLError::End();                              \
-            if (LLError::Log::flush(_out, _site)         \
-                && _site.mLevel == LLError::LEVEL_ERROR) \
+            if (LLError::Log::flush(_out, _site))        \
                 LLERROR_CRASH                            \
         }                                                \
 	} while(0)
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 7ca6ddb737..af46430f74 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -92,11 +92,19 @@ namespace LLError
 	/*
 		Control functions.
 	*/
+
 	typedef boost::function<void(const std::string&)> FatalFunction;
 
-    LL_COMMON_API void overrideCrashOnError(const FatalFunction&);
-    LL_COMMON_API void restoreCrashOnError();
-    
+	/// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code
+	LL_COMMON_API void overrideCrashOnError(const FatalFunction&);
+		// The fatal function will be called when an message of LEVEL_ERROR
+		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
+		// (by, for example, setting a class level to LEVEL_NONE), will keep
+		// the that message from causing the fatal funciton to be invoked.
+
+    /// Undo the effect of the overrideCrashOnError above
+	LL_COMMON_API void restoreCrashOnError();
+
 	LL_COMMON_API std::string getFatalMessage();
 		// Retrieve the message last passed to LL_ERRS, if any
 
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index f7bfa36bb5..bf20c87c89 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -59,6 +59,7 @@ public:
         // pump name -- so it should NOT need tweaking for uniqueness.
         mReplyPump(LLUUID::generateNewID().asString()),
         mExpect(0),
+
         // Instantiate a distinct LLLeapListener for this plugin. (Every
         // plugin will want its own collection of managed listeners, etc.)
         // Pass it a callback to our connect() method, so it can send events
@@ -144,9 +145,6 @@ public:
         mStderrConnection = childerr.getPump()
             .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
 
-        // For our lifespan, intercept any LL_ERRS so we can notify plugin
-        LLError::overrideCrashOnError(boost::bind(&LLLeapImpl::fatalFunction, this, _1));
-
         // Send child a preliminary event reporting our own reply-pump name --
         // which would otherwise be pretty tricky to guess!
         wstdin(mReplyPump.getName(),
@@ -161,8 +159,6 @@ public:
     virtual ~LLLeapImpl()
     {
         LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
-        // Restore original fatal crash behavior for LL_ERRS
-        LLError::restoreCrashOnError();
     }
 
     // Listener for failed launch attempt
@@ -376,30 +372,6 @@ public:
         return false;
     }
 
-    void fatalFunction(const std::string& error)
-    {
-        // Notify plugin
-        LLSD event;
-        event["type"] = "error";
-        event["error"] = error;
-        mReplyPump.post(event);
-
-        // All the above really accomplished was to buffer the serialized
-        // event in our WritePipe. Have to pump mainloop a couple times to
-        // really write it out there... but time out in case we can't write.
-        LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
-        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-        LLSD nop;
-        F64 until = (LLTimer::getElapsedSeconds() + 2).value();
-        while (childin.size() && LLTimer::getElapsedSeconds() < until)
-        {
-            mainloop.post(nop);
-        }
-
-        // go ahead and do the crash that LLError would have done
-        LLERROR_CRASH
-    }
-
 private:
     /// We always want to listen on mReplyPump with wstdin(); under some
     /// circumstances we'll also echo other LLEventPumps to the plugin.
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index b280271476..fedc17dbe9 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -50,11 +50,11 @@ extern void wouldHaveCrashed(const std::string& message);
 
 struct WrapLLErrs
 {
-    WrapLLErrs():
+    WrapLLErrs()
         // Resetting Settings discards the default Recorder that writes to
         // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
         // console output of successful tests, potentially confusing things.
-        mPriorErrorSettings(LLError::saveAndResetSettings())
+    :mPriorErrorSettings(LLError::saveAndResetSettings())
     {
         // Make LL_ERRS call our own operator() method
         LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1));
@@ -210,6 +210,7 @@ public:
     {
         LLError::removeRecorder(mRecorder);
         LLError::restoreSettings(mOldSettings);
+        LLError::restoreCrashOnError();
     }
 
     /// Don't assume the message we want is necessarily the LAST log message
diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index 9dbc6f447e..286c275b90 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -13,6 +13,7 @@ include(LLAddBuildTest)
 include(LLMessage)
 include(LLCommon)
 include(Tut)
+include(bugsplat)
 
 include_directories (${CMAKE_CURRENT_SOURCE_DIR})
 
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index 293ada7548..28b8e8c06d 100644
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -11,6 +11,7 @@ include(LLKDU)
 include(LLImageJ2COJ)
 include(ZLIB)
 include(LLAddBuildTest)
+include(bugsplat)
 include(Tut)
 
 include_directories(
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 379c3ee9ea..625459823c 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -4,6 +4,7 @@ project(llmath)
 
 include(00-Common)
 include(LLCommon)
+include(bugsplat)
 include(Boost)
 
 include_directories(
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 04f6c9b7f0..bbfa838827 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -8,9 +8,7 @@ include(00-Common)
 include(Linking)
 
 include(Boost)
-if (BUGSPLAT_DB)
-  include(bugsplat)
-endif (BUGSPLAT_DB)
+include(bugsplat)
 include(BuildPackagesInfo)
 include(BuildVersion)
 include(CMakeCopyIfDifferent)
@@ -97,18 +95,18 @@ include_directories(
     ${CMAKE_CURRENT_SOURCE_DIR}
     )
 
-if (BUGSPLAT_DB)
-  include_directories(
-    ${BUGSPLAT_INCLUDE_DIR}
-    )
-endif (BUGSPLAT_DB)
-
 include_directories(SYSTEM
     ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
     ${LLXML_SYSTEM_INCLUDE_DIRS}
     ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}
     )
 
+if (USE_BUGSPLAT)
+  include_directories(AFTER
+    ${BUGSPLAT_INCLUDE_DIR}
+    )
+endif (USE_BUGSPLAT)
+
 set(viewer_SOURCE_FILES
     groupchatlistener.cpp
     llaccountingcostmanager.cpp
@@ -1390,11 +1388,11 @@ if (DARWIN)
     ${COREAUDIO_LIBRARY}
     )
 
-  if (BUGSPLAT_DB)
+  if (USE_BUGSPLAT)
     list(APPEND viewer_LIBRARIES
       ${BUGSPLAT_LIBRARIES}
       )
-  endif (BUGSPLAT_DB)
+  endif (USE_BUGSPLAT)
 
   # Add resource files to the project.
   set(viewer_RESOURCE_FILES
@@ -1729,10 +1727,10 @@ if (SDL_FOUND)
     )
 endif (SDL_FOUND)
 
-if (BUGSPLAT_DB)
+if (USE_BUGSPLAT)
   set_property(TARGET ${VIEWER_BINARY_NAME}
     PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT")
-endif (BUGSPLAT_DB)
+endif (USE_BUGSPLAT)
 
 # add package files
 file(GLOB EVENT_HOST_SCRIPT_GLOB_LIST
@@ -2018,11 +2016,11 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${LLAPPEARANCE_LIBRARIES}
     )
 
-if (BUGSPLAT_DB)
+if (USE_BUGSPLAT)
   target_link_libraries(${VIEWER_BINARY_NAME}
     ${BUGSPLAT_LIBRARIES}
     )
-endif (BUGSPLAT_DB)
+endif (USE_BUGSPLAT)
 
 set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
     "Path to artwork files.")
@@ -2206,7 +2204,7 @@ endif (INSTALL)
 
 # Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh
 if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE)
-  if (NOT BUGSPLAT_DB)
+  if (NOT USE_BUGSPLAT)
     # Breakpad symbol-file generation
     set(SYMBOL_SEARCH_DIRS "")
     if (WINDOWS)
@@ -2261,7 +2259,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
       add_dependencies(generate_symbols "${VIEWER_COPY_MANIFEST}")
     endif (WINDOWS OR LINUX)
 
-  else (NOT BUGSPLAT_DB)
+  else (NOT USE_BUGSPLAT)
     # BugSplat symbol-file generation
     if (WINDOWS)
       # Just pack up a tarball containing only the .pdb file for the
@@ -2345,9 +2343,9 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
     if (LINUX)
       # TBD
     endif (LINUX)
-  endif (NOT BUGSPLAT_DB)
+  endif (NOT USE_BUGSPLAT)
 
-  # for both BUGSPLAT_DB and Breakpad
+  # for both Bugsplat and Breakpad
   add_dependencies(llpackage generate_symbols)
 endif ()
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 1fda07edd6..f9ee22d20a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -719,14 +719,14 @@ LLAppViewer::LLAppViewer()
 	// from the previous viewer run between this constructor call and the
 	// init() call, which will overwrite the static_debug_info.log file for
 	// THIS run. So setDebugFileNames() early.
-#if LL_BUGSPLAT
+#   ifdef LL_BUGSPLAT
 	// MAINT-8917: don't create a dump directory just for the
 	// static_debug_info.log file
 	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
-#else // ! LL_BUGSPLAT
+#   else // ! LL_BUGSPLAT
 	// write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues.
 	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
-#endif // ! LL_BUGSPLAT
+#   endif // ! LL_BUGSPLAT
 	mDumpPath = logdir;
 	setMiniDumpDir(logdir);
 	setDebugFileNames(logdir);
@@ -751,6 +751,16 @@ public:
 	}
 };
 
+namespace {
+// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide
+// this little helper function.
+void fast_exit(int rc)
+{
+	_exit(rc);
+}
+
+
+}
 
 bool LLAppViewer::init()
 {
@@ -790,6 +800,18 @@ bool LLAppViewer::init()
 	initMaxHeapSize() ;
 	LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
 
+	// Although initLoggingAndGetLastDuration() is the right place to mess with
+	// overrideCrashOnError(), we can't query gSavedSettings until after
+	// initConfiguration().
+	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
+	if (rc >= 0)
+	{
+		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
+		// fast_exit() rather than exit() because normal cleanup depends too
+		// much on successful startup!
+		LLError::overrideCrashOnError(boost::bind(fast_exit, rc));
+	}
+
     mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
 
 	// Initialize the non-LLCurl libcurl library.  Should be called
@@ -2096,9 +2118,6 @@ bool LLAppViewer::cleanup()
 	return true;
 }
 
-	gDebugInfo["FatalMessage"] = error_string;
-	LLAppViewer::instance()->writeDebugInfo();
-
 bool LLAppViewer::initThreads()
 {
 	static const bool enable_threads = true;
@@ -2133,6 +2152,24 @@ bool LLAppViewer::initThreads()
 	return true;
 }
 
+#ifndef LL_BUGSPLAT
+void errorCallback(const std::string &error_string)
+{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
+#endif
+
+	//Set the ErrorActivated global so we know to create a marker file
+	gLLErrorActivated = true;
+
+	gDebugInfo["FatalMessage"] = error_string;
+	// We're not already crashing -- we simply *intend* to crash. Since we
+	// haven't actually trashed anything yet, we can afford to write the whole
+	// static info file.
+	LLAppViewer::instance()->writeDebugInfo();
+}
+#endif // ! LL_BUGSPLAT
+
 void LLAppViewer::initLoggingAndGetLastDuration()
 {
 	//
@@ -2889,7 +2926,6 @@ bool LLAppViewer::initWindow()
 	// Need to load feature table before cheking to start watchdog.
 	bool use_watchdog = false;
 	int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
-
 	if (watchdog_enabled_setting == -1)
 	{
 		use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
@@ -3352,10 +3388,19 @@ void LLAppViewer::writeSystemInfo()
 	gDebugInfo["MainloopThreadID"] = (S32)thread_id;
 #endif
 
+#ifndef LL_BUGSPLAT
+	// "CrashNotHandled" is set here, while things are running well,
+	// in case of a freeze. If there is a freeze, the crash logger will be launched
+	// and can read this value from the debug_info.log.
+	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
+	// then the value of "CrashNotHandled" will be set to true.
+	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
+#else // LL_BUGSPLAT
 	// "CrashNotHandled" is obsolete; it used (not very successsfully)
     // to try to distinguish crashes from freezes
 	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
     gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
+#endif // ! LL_BUGSPLAT
 
 	// Insert crash host url (url to post crash log to) if configured. This insures
 	// that the crash report will go to the proper location in the case of a
diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp
index 2f3e5db84f..0a01113224 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/newview/llwatchdog.cpp
@@ -145,10 +145,10 @@ void LLWatchdogTimeout::ping(const std::string& state)
 }
 
 // LLWatchdog
-LLWatchdog::LLWatchdog() :
-	mSuspectsAccessMutex(),
-	mTimer(NULL),
-	mLastClockCount(0)
+LLWatchdog::LLWatchdog()
+    :mSuspectsAccessMutex()
+    ,mTimer(NULL)
+	,mLastClockCount(0)
 {
 }
 
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index 8344cead57..7ac1f1db23 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -13,7 +13,7 @@ include(LLXML)
 include(Linking)
 include(Tut)
 include(LLAddBuildTest)
-
+include(bugsplat)
 include(GoogleMock)
 
 include_directories(
@@ -82,6 +82,10 @@ list(APPEND test_SOURCE_FILES ${test_HEADER_FILES})
 
 add_executable(lltest ${test_SOURCE_FILES})
 
+if (USE_BUGSPLAT)
+  set_target_properties(lltest PROPERTIES COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
+endif (USE_BUGSPLAT)
+
 target_link_libraries(lltest
     ${LLDATABASE_LIBRARIES}
     ${LLINVENTORY_LIBRARIES}
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 125de72b79..5dabcbbc58 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -75,7 +75,10 @@
 
 #include <fstream>
 
-void wouldHaveCrashed(const std::string& message);
+void wouldHaveCrashed(const std::string& message)
+{
+	tut::fail("fatal error message: " + message);
+}
 
 namespace tut
 {
@@ -506,11 +509,6 @@ void stream_groups(std::ostream& s, const char* app)
 	}
 }
 
-void wouldHaveCrashed(const std::string& message)
-{
-	tut::fail("fatal error message: " + message);
-}
-
 static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
 
 int main(int argc, char **argv)
-- 
cgit v1.2.3


From e86c0b3d0fbc5f91090241be959ef19bfffd8636 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 5 Mar 2019 04:44:29 -0500
Subject: fix error message reporting?

---
 indra/llcommon/llerror.cpp            | 18 +++++++--------
 indra/llcommon/llerror.h              |  6 +++--
 indra/llcommon/llerrorcontrol.h       | 11 ++++++---
 indra/llcommon/tests/llerror_test.cpp |  8 +++++--
 indra/llcommon/tests/wrapllerrs.h     |  8 +++----
 indra/newview/llappviewer.cpp         | 43 ++++++++++++-----------------------
 indra/newview/llappviewermacosx.cpp   |  6 ++---
 indra/test/test.cpp                   |  7 +++---
 8 files changed, 51 insertions(+), 56 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 77d7fe1b24..6fa9e590cb 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -719,7 +719,7 @@ namespace LLError
 		commonInit(user_dir, app_dir, log_to_stderr);
 	}
 
-	void overrideCrashOnError(const FatalFunction& fatal_function)
+	void setFatalHandler(const FatalFunction& fatal_function)
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		s->mCrashFunction = fatal_function;
@@ -1306,12 +1306,12 @@ namespace LLError
 		return ;
 	}
 
-	bool Log::flush(std::ostringstream* out, const CallSite& site)
+	ErrCrashHandlerResult Log::flush(std::ostringstream* out, const CallSite& site)
 	{
 		LLMutexTrylock lock(&gLogMutex,5);
 		if (!lock.isLocked())
 		{
-			return false; // because this wasn't logged, it cannot be fatal
+			return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
 		}
 
 		// If we hit a logging request very late during shutdown processing,
@@ -1319,7 +1319,7 @@ namespace LLError
 		// DO NOT resurrect them.
 		if (Settings::wasDeleted() || Globals::wasDeleted())
 		{
-            return false; // because this wasn't logged, it cannot be fatal
+            return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
 		}
 
 		Globals* g = Globals::getInstance();
@@ -1353,7 +1353,7 @@ namespace LLError
 				} 
 				else
 				{
-					return false; // because this wasn't logged, it cannot be fatal
+					return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
 				}
 			}
 			else 
@@ -1369,20 +1369,18 @@ namespace LLError
 
 		if (site.mLevel == LEVEL_ERROR)
 		{
-			g->mFatalMessage = message;
             if (s->mCrashFunction)
             {
-                s->mCrashFunction(message);
-                return false; // because an override is in effect
+                return s->mCrashFunction(message);
             }
             else
             {
-                return true; // calling macro should crash
+                return ERR_CRASH; // calling macro should crash
             }
 		}
         else
         {
-            return false; // not ERROR, so do not crash
+            return ERR_DO_NOT_CRASH; // not ERROR, so do not crash
         }
 	}
 }
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 07aa5c6f8b..2a73ccb36a 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -194,6 +194,8 @@ namespace LLError
 	
 	struct CallSite;
 	
+    enum ErrCrashHandlerResult { ERR_DO_NOT_CRASH, ERR_CRASH };
+
 	class LL_COMMON_API Log
 	{
 	public:
@@ -203,7 +205,7 @@ namespace LLError
 		static void flush(std::ostringstream* out, char* message);
 
         // returns false iff the calling macro should crash
-		static bool flush(std::ostringstream*, const CallSite&);
+		static ErrCrashHandlerResult flush(std::ostringstream*, const CallSite&);
 
 		static std::string demangle(const char* mangled);
 	};
@@ -386,7 +388,7 @@ volatile extern int* gCauseCrash;
 
 #define LL_ENDL                                          \
 			LLError::End();                              \
-            if (LLError::Log::flush(_out, _site))        \
+            if (LLError::ERR_CRASH == LLError::Log::flush(_out, _site)) \
                 LLERROR_CRASH                            \
         }                                                \
 	} while(0)
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index af46430f74..2fa220ba5a 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -93,16 +93,21 @@ namespace LLError
 		Control functions.
 	*/
 
-	typedef boost::function<void(const std::string&)> FatalFunction;
+    // A FatalFunction is called if set using setFatalHandler; its return controls
+    // whether or not the calling error logging code should crash.
+    // ERR_DO_NOT_CRASH should be used only in test code.
+	typedef boost::function<LLError::ErrCrashHandlerResult(const std::string&)> FatalFunction;
+    
 
 	/// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code
-	LL_COMMON_API void overrideCrashOnError(const FatalFunction&);
+	LL_COMMON_API void setFatalHandler(const FatalFunction&);
 		// The fatal function will be called when an message of LEVEL_ERROR
 		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
 		// (by, for example, setting a class level to LEVEL_NONE), will keep
 		// the that message from causing the fatal funciton to be invoked.
+        // The 
 
-    /// Undo the effect of the overrideCrashOnError above
+    /// Undo the effect of the setFatalHandler above
 	LL_COMMON_API void restoreCrashOnError();
 
 	LL_COMMON_API std::string getFatalMessage();
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 2f8923d2de..9dcb5c145f 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -70,7 +70,11 @@ namespace
 namespace
 {
 	static bool fatalWasCalled;
-	void fatalCall(const std::string&) { fatalWasCalled = true; }
+    LLError::ErrCrashHandlerResult fatalCall(const std::string&)
+    {
+        fatalWasCalled = true;
+        return LLError::ERR_DO_NOT_CRASH;
+    }
 }
 
 namespace tut
@@ -120,7 +124,7 @@ namespace tut
 
 			mPriorErrorSettings = LLError::saveAndResetSettings();
 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
-			LLError::overrideCrashOnError(fatalCall);
+			LLError::setFatalHandler(fatalCall);
 			LLError::addRecorder(mRecorder);
 		}
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index fedc17dbe9..a412e12a04 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -46,7 +46,7 @@
 
 // statically reference the function in test.cpp... it's short, we could
 // replicate, but better to reuse
-extern void wouldHaveCrashed(const std::string& message);
+extern LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message);
 
 struct WrapLLErrs
 {
@@ -57,7 +57,7 @@ struct WrapLLErrs
     :mPriorErrorSettings(LLError::saveAndResetSettings())
     {
         // Make LL_ERRS call our own operator() method
-        LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1));
+        LLError::setFatalHandler(boost::bind(&WrapLLErrs::operator(), this, _1));
     }
 
     ~WrapLLErrs()
@@ -71,7 +71,7 @@ struct WrapLLErrs
         FatalException(const std::string& what): LLException(what) {}
     };
 
-    void operator()(const std::string& message)
+    LLError::ErrCrashHandlerResult operator()(const std::string& message)
     {
         // Save message for later in case consumer wants to sense the result directly
         error = message;
@@ -201,7 +201,7 @@ public:
         mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new CaptureLogRecorder())
     {
-        LLError::overrideCrashOnError(wouldHaveCrashed);
+        LLError::setFatalHandler(wouldHaveCrashed);
         LLError::setDefaultLevel(level);
         LLError::addRecorder(mRecorder);
     }
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f9ee22d20a..8b9f9085b1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -751,16 +751,7 @@ public:
 	}
 };
 
-namespace {
-// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide
-// this little helper function.
-void fast_exit(int rc)
-{
-	_exit(rc);
-}
-
-
-}
+static S32 sQAModeTermCode = 0; // set from QAModeTermCode to specify exit code for LL_ERRS
 
 bool LLAppViewer::init()
 {
@@ -800,17 +791,8 @@ bool LLAppViewer::init()
 	initMaxHeapSize() ;
 	LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
 
-	// Although initLoggingAndGetLastDuration() is the right place to mess with
-	// overrideCrashOnError(), we can't query gSavedSettings until after
-	// initConfiguration().
-	S32 rc(gSavedSettings.getS32("QAModeTermCode"));
-	if (rc >= 0)
-	{
-		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
-		// fast_exit() rather than exit() because normal cleanup depends too
-		// much on successful startup!
-		LLError::overrideCrashOnError(boost::bind(fast_exit, rc));
-	}
+    // if a return code is set for error exit, save it here for use in fatalErrorHandler
+    sQAModeTermCode = gSavedSettings.getS32("QAModeTermCode");
 
     mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
 
@@ -2152,8 +2134,7 @@ bool LLAppViewer::initThreads()
 	return true;
 }
 
-#ifndef LL_BUGSPLAT
-void errorCallback(const std::string &error_string)
+LLError::ErrCrashHandlerResult fatalErrorHandler(const std::string &error_string)
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
@@ -2167,8 +2148,15 @@ void errorCallback(const std::string &error_string)
 	// haven't actually trashed anything yet, we can afford to write the whole
 	// static info file.
 	LLAppViewer::instance()->writeDebugInfo();
+
+    if (sQAModeTermCode)
+    {
+        _exit(sQAModeTermCode);
+        return LLError::ERR_DO_NOT_CRASH; // notreached
+    }
+
+    return LLError::ERR_CRASH;
 }
-#endif // ! LL_BUGSPLAT
 
 void LLAppViewer::initLoggingAndGetLastDuration()
 {
@@ -2178,6 +2166,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
                                 ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
                                 );
+	LLError::setFatalHandler(fatalErrorHandler);
 
 	// Remove the last ".old" log file.
 	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
@@ -3728,12 +3717,8 @@ void LLAppViewer::processMarkerFiles()
 		else if (marker_is_same_version)
 		{
 			// the file existed, is ours, and matched our version, so we can report on what it says
-			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL;
-#           if LL_BUGSPLAT            
+			LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
 			gLastExecEvent = LAST_EXEC_OTHER_CRASH;
-#           else
-			gLastExecEvent = LAST_EXEC_FROZE;
-#           endif
 		}
 		else
 		{
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 3111540a13..9c2e6eadca 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -188,17 +188,17 @@ CrashMetadataSingleton::CrashMetadataSingleton()
     LLSD info;
     if (! static_file.is_open())
     {
-        LL_INFOS() << "Can't open '" << staticDebugPathname
+        LL_WARNS() << "Can't open '" << staticDebugPathname
                    << "'; no metadata about previous run" << LL_ENDL;
     }
     else if (! LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED))
     {
-        LL_INFOS() << "Can't parse '" << staticDebugPathname
+        LL_WARNS() << "Can't parse '" << staticDebugPathname
                    << "'; no metadata about previous run" << LL_ENDL;
     }
     else
     {
-        LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL;
+        LL_INFOS() << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL;
         logFilePathname      = get_metadata(info, "SLLog");
         userSettingsPathname = get_metadata(info, "SettingsFilename");
         OSInfo               = get_metadata(info, "OSInfo");
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 5dabcbbc58..4f966aede8 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -75,9 +75,10 @@
 
 #include <fstream>
 
-void wouldHaveCrashed(const std::string& message)
+LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message)
 {
 	tut::fail("fatal error message: " + message);
+    return LLError::ERR_DO_NOT_CRASH;
 }
 
 namespace tut
@@ -149,7 +150,7 @@ public:
 		mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new RecordToTempFile(pool))
 	{
-		LLError::overrideCrashOnError(wouldHaveCrashed);
+		LLError::setFatalHandler(wouldHaveCrashed);
 		LLError::setDefaultLevel(level);
 		LLError::addRecorder(mRecorder);
 	}
@@ -530,7 +531,7 @@ int main(int argc, char **argv)
 		LLError::initForApplication(".", ".", false /* do not log to stderr */);
 		LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
 	}	
-	LLError::overrideCrashOnError(wouldHaveCrashed);
+	LLError::setFatalHandler(wouldHaveCrashed);
 	std::string test_app_name(argv[0]);
 	std::string test_log = test_app_name + ".log";
 	LLFile::remove(test_log);
-- 
cgit v1.2.3


From 07870a9ebb17e7a31df276f4ac2d8f52fec2a3b0 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 5 Mar 2019 13:57:02 -0500
Subject: rename crash handler to hook, and make them chainable by putting back
 the get and documenting it

---
 indra/llcommon/llerror.cpp            | 18 +++++++++---------
 indra/llcommon/llerror.h              |  6 +++---
 indra/llcommon/llerrorcontrol.h       | 26 ++++++++++++++------------
 indra/llcommon/llleap.cpp             | 32 +++++++++++++++++++++++++++++++-
 indra/llcommon/tests/llerror_test.cpp |  4 ++--
 indra/llcommon/tests/wrapllerrs.h     | 23 +++++++++++++----------
 indra/newview/llappviewer.cpp         |  4 ++--
 indra/test/test.cpp                   |  6 +++---
 8 files changed, 77 insertions(+), 42 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 6fa9e590cb..5f3edf7f84 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -483,7 +483,7 @@ namespace LLError
 		LevelMap                            mTagLevelMap;
 		std::map<std::string, unsigned int> mUniqueLogMessages;
 		
-		LLError::FatalFunction              mCrashFunction;
+		LLError::FatalHook                  mFatalHook;
 		LLError::TimeFunction               mTimeFunction;
 		
 		Recorders                           mRecorders;
@@ -523,7 +523,7 @@ namespace LLError
 		mFileLevelMap(),
 		mTagLevelMap(),
 		mUniqueLogMessages(),
-		mCrashFunction(NULL),
+		mFatalHook(NULL),
 		mTimeFunction(NULL),
 		mRecorders(),
 		mFileRecorder(),
@@ -719,16 +719,16 @@ namespace LLError
 		commonInit(user_dir, app_dir, log_to_stderr);
 	}
 
-	void setFatalHandler(const FatalFunction& fatal_function)
+	void setFatalHook(const FatalHook& fatal_hook)
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-		s->mCrashFunction = fatal_function;
+		s->mFatalHook = fatal_hook;
 	}
 
-    void restoreCrashOnError()
+	FatalHook getFatalHook()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-		s->mCrashFunction = NULL;
+		return s->mFatalHook;
 	}
 
 	std::string getFatalMessage()
@@ -1306,7 +1306,7 @@ namespace LLError
 		return ;
 	}
 
-	ErrCrashHandlerResult Log::flush(std::ostringstream* out, const CallSite& site)
+	ErrFatalHookResult Log::flush(std::ostringstream* out, const CallSite& site)
 	{
 		LLMutexTrylock lock(&gLogMutex,5);
 		if (!lock.isLocked())
@@ -1369,9 +1369,9 @@ namespace LLError
 
 		if (site.mLevel == LEVEL_ERROR)
 		{
-            if (s->mCrashFunction)
+            if (s->mFatalHook)
             {
-                return s->mCrashFunction(message);
+                return s->mFatalHook(message);
             }
             else
             {
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 2a73ccb36a..6bdb2e852f 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -194,7 +194,7 @@ namespace LLError
 	
 	struct CallSite;
 	
-    enum ErrCrashHandlerResult { ERR_DO_NOT_CRASH, ERR_CRASH };
+    enum ErrFatalHookResult { ERR_DO_NOT_CRASH, ERR_CRASH };
 
 	class LL_COMMON_API Log
 	{
@@ -205,7 +205,7 @@ namespace LLError
 		static void flush(std::ostringstream* out, char* message);
 
         // returns false iff the calling macro should crash
-		static ErrCrashHandlerResult flush(std::ostringstream*, const CallSite&);
+		static ErrFatalHookResult flush(std::ostringstream*, const CallSite&);
 
 		static std::string demangle(const char* mangled);
 	};
@@ -272,7 +272,7 @@ namespace LLError
    //when LLAppViewer::handleViewerCrash() is triggered.
    //
    //Note: to be simple, efficient and necessary to keep track of correct call stacks, 
-	//LLCallStacks is designed not to be thread-safe.
+   //LLCallStacks is designed not to be thread-safe.
    //so try not to use it in multiple parallel threads at same time.
    //Used in a single thread at a time is fine.
    class LL_COMMON_API LLCallStacks
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 2fa220ba5a..e7c5241cc9 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -93,22 +93,24 @@ namespace LLError
 		Control functions.
 	*/
 
-    // A FatalFunction is called if set using setFatalHandler; its return controls
+    // A FatalHook is called if set using setFatalHook; its return controls
     // whether or not the calling error logging code should crash.
     // ERR_DO_NOT_CRASH should be used only in test code.
-	typedef boost::function<LLError::ErrCrashHandlerResult(const std::string&)> FatalFunction;
-    
-
-	/// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code
-	LL_COMMON_API void setFatalHandler(const FatalFunction&);
-		// The fatal function will be called when an message of LEVEL_ERROR
+	typedef boost::function<LLError::ErrFatalHookResult(const std::string&)> FatalHook;
+
+	/// Supplement and control the default behavior of crashing on LL_ERRS
+    /// This may be used to suppress crashes only in test code;
+    /// otherwise, the FatalHook should always either return 
+    /// the result from the previous hook (see getFatalHook below),
+    /// or return LLError::ERR_CRASH
+	LL_COMMON_API void setFatalHook(const FatalHook& fatal_hook);
+		// The fatal_hook function will be called when an message of LEVEL_ERROR
 		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
-		// (by, for example, setting a class level to LEVEL_NONE), will keep
-		// the that message from causing the fatal funciton to be invoked.
-        // The 
+		// (by, for example, setting a class level to LEVEL_NONE), will also
+		// prevent the fatal_hook being called and the resulting deliberate crash
 
-    /// Undo the effect of the setFatalHandler above
-	LL_COMMON_API void restoreCrashOnError();
+    /// Retrieve the previously-set FatalHook
+	LL_COMMON_API FatalHook getFatalHook();
 
 	LL_COMMON_API std::string getFatalMessage();
 		// Retrieve the message last passed to LL_ERRS, if any
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index bf20c87c89..161d25bc34 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -59,7 +59,7 @@ public:
         // pump name -- so it should NOT need tweaking for uniqueness.
         mReplyPump(LLUUID::generateNewID().asString()),
         mExpect(0),
-
+        mPrevFatalHook(LLError::getFatalHook()),
         // Instantiate a distinct LLLeapListener for this plugin. (Every
         // plugin will want its own collection of managed listeners, etc.)
         // Pass it a callback to our connect() method, so it can send events
@@ -145,6 +145,9 @@ public:
         mStderrConnection = childerr.getPump()
             .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
 
+        // For our lifespan, intercept any LL_ERRS so we can notify plugin
+        LLError::setFatalHook(boost::bind(&LLLeapImpl::fatalHook, this, _1));
+
         // Send child a preliminary event reporting our own reply-pump name --
         // which would otherwise be pretty tricky to guess!
         wstdin(mReplyPump.getName(),
@@ -159,6 +162,8 @@ public:
     virtual ~LLLeapImpl()
     {
         LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
+        // Restore original FatalHook
+        LLError::setFatalHook(mPrevFatalHook);
     }
 
     // Listener for failed launch attempt
@@ -372,6 +377,30 @@ public:
         return false;
     }
 
+    LLError::ErrFatalHookResult fatalHook(const std::string& error)
+    {
+        // Notify plugin
+        LLSD event;
+        event["type"] = "error";
+        event["error"] = error;
+        mReplyPump.post(event);
+
+        // All the above really accomplished was to buffer the serialized
+        // event in our WritePipe. Have to pump mainloop a couple times to
+        // really write it out there... but time out in case we can't write.
+        LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
+        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+        LLSD nop;
+        F64 until = (LLTimer::getElapsedSeconds() + 2).value();
+        while (childin.size() && LLTimer::getElapsedSeconds() < until)
+        {
+            mainloop.post(nop);
+        }
+
+        // forward the call to the previous FatalHook, default to crashing if there isn't one
+        return mPrevFatalHook ? mPrevFatalHook(error) : LLError::ERR_CRASH;
+    }
+
 private:
     /// We always want to listen on mReplyPump with wstdin(); under some
     /// circumstances we'll also echo other LLEventPumps to the plugin.
@@ -392,6 +421,7 @@ private:
         mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
     boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
     LLProcess::ReadPipe::size_type mExpect;
+    LLError::FatalHook mPrevFatalHook;
     boost::scoped_ptr<LLLeapListener> mListener;
 };
 
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 9dcb5c145f..9895abc1f3 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -70,7 +70,7 @@ namespace
 namespace
 {
 	static bool fatalWasCalled;
-    LLError::ErrCrashHandlerResult fatalCall(const std::string&)
+    LLError::ErrFatalHookResult fatalHook(const std::string&)
     {
         fatalWasCalled = true;
         return LLError::ERR_DO_NOT_CRASH;
@@ -124,7 +124,7 @@ namespace tut
 
 			mPriorErrorSettings = LLError::saveAndResetSettings();
 			LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
-			LLError::setFatalHandler(fatalCall);
+			LLError::setFatalHook(fatalHook);
 			LLError::addRecorder(mRecorder);
 		}
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index a412e12a04..a6c44d5fdd 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -46,7 +46,7 @@
 
 // statically reference the function in test.cpp... it's short, we could
 // replicate, but better to reuse
-extern LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message);
+extern LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message);
 
 struct WrapLLErrs
 {
@@ -55,14 +55,15 @@ struct WrapLLErrs
         // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
         // console output of successful tests, potentially confusing things.
     :mPriorErrorSettings(LLError::saveAndResetSettings())
+    ,mPriorFatalHook(LLError::getFatalHook())
     {
         // Make LL_ERRS call our own operator() method
-        LLError::setFatalHandler(boost::bind(&WrapLLErrs::operator(), this, _1));
+        LLError::setFatalHook(boost::bind(&WrapLLErrs::operator(), this, _1));
     }
 
     ~WrapLLErrs()
     {
-        LLError::restoreCrashOnError();
+        LLError::setFatalHook(mPriorFatalHook);
         LLError::restoreSettings(mPriorErrorSettings);
     }
 
@@ -71,7 +72,7 @@ struct WrapLLErrs
         FatalException(const std::string& what): LLException(what) {}
     };
 
-    LLError::ErrCrashHandlerResult operator()(const std::string& message)
+    LLError::ErrFatalHookResult operator()(const std::string& message)
     {
         // Save message for later in case consumer wants to sense the result directly
         error = message;
@@ -107,7 +108,7 @@ struct WrapLLErrs
 
     std::string error;
     LLError::SettingsStoragePtr mPriorErrorSettings;
-    LLError::FatalFunction mPriorFatal;
+    LLError::FatalHook mPriorFatalHook;
 };
 
 /**
@@ -197,11 +198,12 @@ public:
         // with that output. If it turns out that saveAndResetSettings() has
         // some bad effect, give up and just let the DEBUG level log messages
         // display.
-		: boost::noncopyable(),
-        mOldSettings(LLError::saveAndResetSettings()),
-		mRecorder(new CaptureLogRecorder())
+		: boost::noncopyable()
+        , mOldSettings(LLError::saveAndResetSettings())
+		, mPriorFatalHook(LLError::getFatalHook())
+		, mRecorder(new CaptureLogRecorder())
     {
-        LLError::setFatalHandler(wouldHaveCrashed);
+        LLError::setFatalHook(wouldHaveCrashed);
         LLError::setDefaultLevel(level);
         LLError::addRecorder(mRecorder);
     }
@@ -210,7 +212,7 @@ public:
     {
         LLError::removeRecorder(mRecorder);
         LLError::restoreSettings(mOldSettings);
-        LLError::restoreCrashOnError();
+        LLError::setFatalHook(mPriorFatalHook);
     }
 
     /// Don't assume the message we want is necessarily the LAST log message
@@ -228,6 +230,7 @@ public:
 
 private:
     LLError::SettingsStoragePtr mOldSettings;
+    LLError::FatalHook   mPriorFatalHook;
 	LLError::RecorderPtr mRecorder;
 };
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 8b9f9085b1..8616fe7c76 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2134,7 +2134,7 @@ bool LLAppViewer::initThreads()
 	return true;
 }
 
-LLError::ErrCrashHandlerResult fatalErrorHandler(const std::string &error_string)
+LLError::ErrFatalHookResult fatalErrorHook(const std::string &error_string)
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
@@ -2166,7 +2166,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
                                 ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
                                 );
-	LLError::setFatalHandler(fatalErrorHandler);
+	LLError::setFatalHook(fatalErrorHook);
 
 	// Remove the last ".old" log file.
 	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 4f966aede8..52ac855d9f 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -75,7 +75,7 @@
 
 #include <fstream>
 
-LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message)
+LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message)
 {
 	tut::fail("fatal error message: " + message);
     return LLError::ERR_DO_NOT_CRASH;
@@ -150,7 +150,7 @@ public:
 		mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new RecordToTempFile(pool))
 	{
-		LLError::setFatalHandler(wouldHaveCrashed);
+		LLError::setFatalHook(wouldHaveCrashed);
 		LLError::setDefaultLevel(level);
 		LLError::addRecorder(mRecorder);
 	}
@@ -531,7 +531,7 @@ int main(int argc, char **argv)
 		LLError::initForApplication(".", ".", false /* do not log to stderr */);
 		LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
 	}	
-	LLError::setFatalHandler(wouldHaveCrashed);
+	LLError::setFatalHook(wouldHaveCrashed);
 	std::string test_app_name(argv[0]);
 	std::string test_log = test_app_name + ".log";
 	LLFile::remove(test_log);
-- 
cgit v1.2.3


From 46fb225134ef871a686d0571cc55256923eee110 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 21 May 2019 12:09:26 -0400
Subject: suppress unreachable code warning because tut::fail triggers it

---
 indra/test/test.cpp | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

(limited to 'indra')

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 52ac855d9f..9d327ff3be 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -57,16 +57,11 @@
 #include <gtest/gtest.h>
 #endif
 
-#if LL_MSVC
-#pragma warning (push)
+#if LL_WINDOWS
 #pragma warning (disable : 4702) // warning C4702: unreachable code
 #endif
 #include <boost/iostreams/tee.hpp>
 #include <boost/iostreams/stream.hpp>
-#if LL_MSVC
-#pragma warning (pop)
-#endif
-
 #include <boost/scoped_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/make_shared.hpp>
-- 
cgit v1.2.3


From 1e98a607d08019f66ae878e4cb247e850a7443cf Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 4 Jun 2019 10:06:43 -0400
Subject: try putting fatal message into dynamic crash data

---
 indra/newview/llappviewer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 8616fe7c76..0e97ed5a47 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3388,7 +3388,7 @@ void LLAppViewer::writeSystemInfo()
 	// "CrashNotHandled" is obsolete; it used (not very successsfully)
     // to try to distinguish crashes from freezes
 	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
-    gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
+    gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage();
 #endif // ! LL_BUGSPLAT
 
 	// Insert crash host url (url to post crash log to) if configured. This insures
-- 
cgit v1.2.3


From e711376cc75a51973291d1730467c0b6e3a74226 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 5 Jun 2019 14:27:48 -0400
Subject: assorted cleanup

---
 indra/llcommon/llapp.cpp            |  5 +++++
 indra/newview/CMakeLists.txt        |  2 +-
 indra/newview/llappdelegate-objc.mm |  2 ++
 indra/newview/llappviewer.cpp       | 10 ++--------
 indra/newview/llappviewerwin32.cpp  |  3 +--
 indra/newview/llviewerwindow.cpp    |  3 ++-
 6 files changed, 13 insertions(+), 12 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 421af3006e..34c969437b 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -526,7 +526,12 @@ void LLApp::setupErrorHandling(bool second_instance)
 #endif // LL_LINUX
 
 #endif // ! LL_WINDOWS
+
+#ifdef LL_BUGSPLAT
+    // do not start our own error thread
+#else // ! LL_BUGSPLAT
 	startErrorThread();
+#endif
 }
 
 void LLApp::startErrorThread()
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index bbfa838827..fd520d2c6f 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1729,7 +1729,7 @@ endif (SDL_FOUND)
 
 if (USE_BUGSPLAT)
   set_property(TARGET ${VIEWER_BINARY_NAME}
-    PROPERTY COMPILE_DEFINITIONS "LL_BUGSPLAT")
+    PROPERTY COMPILE_DEFINITIONS "${BUGSPLAT_DEFINE}")
 endif (USE_BUGSPLAT)
 
 # add package files
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 47fde299c7..30bfe1f439 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -66,6 +66,7 @@
 	constructViewer();
 
 #if defined(LL_BUGSPLAT)
+    infos("bugsplat setup");
 	// Engage BugsplatStartupManager *before* calling initViewer() to handle
 	// any crashes during initialization.
 	// https://www.bugsplat.com/docs/platforms/os-x#initialization
@@ -74,6 +75,7 @@
 	[BugsplatStartupManager sharedManager].delegate = self;
 	[[BugsplatStartupManager sharedManager] start];
 #endif
+    infos("post-bugsplat setup");
 
 	frameTimer = nil;
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0e97ed5a47..35f9d7f4fd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3386,9 +3386,8 @@ void LLAppViewer::writeSystemInfo()
 	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
 #else // LL_BUGSPLAT
 	// "CrashNotHandled" is obsolete; it used (not very successsfully)
-    // to try to distinguish crashes from freezes
+    // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze
 	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
-    gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage();
 #endif // ! LL_BUGSPLAT
 
 	// Insert crash host url (url to post crash log to) if configured. This insures
@@ -3617,7 +3616,7 @@ void LLAppViewer::handleViewerCrash()
 
 	if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
 
-	gDebugInfo["Dynamic"]["FatalMessage"] = LLError::getFatalMessage();
+	gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
 
 	// Close the debug file
 	pApp->writeDebugInfo(false);  //false answers the isStatic question with the least overhead.
@@ -5476,11 +5475,6 @@ void LLAppViewer::pauseMainloopTimeout()
 
 void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
 {
-//	if(!restoreErrorTrap())
-//	{
-//		LL_WARNS() << "!!!!!!!!!!!!! Its an error trap!!!!" << state << LL_ENDL;
-//	}
-
 	if(mMainloopTimeout)
 	{
 		if(secs < 0.0f)
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index d208e135bb..6a6cc225d4 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -802,8 +802,7 @@ bool LLAppViewerWin32::beingDebugged()
 
 bool LLAppViewerWin32::restoreErrorTrap()
 {	
-	return true;
-	//return LLWinDebug::checkExceptionHandler();
+	return false;
 }
 
 void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c214984e1d..b0f5b550e6 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1791,7 +1791,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 	
 	if (!LLAppViewer::instance()->restoreErrorTrap())
 	{
-		LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
+        // this always happens, so downgrading it to INFO
+		LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL;
 	}
 
 	const bool do_not_enforce = false;
-- 
cgit v1.2.3


From b6f1529b5abaf36b15efb6d9215bcc89e6a3f167 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Thu, 6 Jun 2019 09:25:15 -0400
Subject: remove the old crash logger modules when using BugSplat

---
 indra/CMakeLists.txt         | 40 +++++++++++++++++++++++-----------------
 indra/newview/CMakeLists.txt | 28 +++++++++++++++++++---------
 2 files changed, 42 insertions(+), 26 deletions(-)

(limited to 'indra')

diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index cf6029c4ae..4dd2dcc2e9 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -60,29 +60,18 @@ add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins)
 endif (ENABLE_MEDIA_PLUGINS)
 
 if (LINUX)
-  add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
   if (INSTALL_PROPRIETARY)
       include(LLAppearanceUtility)
       add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR})
   endif (INSTALL_PROPRIETARY)
-  add_dependencies(viewer linux-crash-logger-strip-target)
-elseif (DARWIN)
-  add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
-  add_dependencies(viewer mac-crash-logger)
-elseif (WINDOWS)
-  add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
-  # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
-  if (EXISTS ${VIEWER_DIR}win_setup)
-    add_subdirectory(${VIEWER_DIR}win_setup)
-  endif (EXISTS ${VIEWER_DIR}win_setup)
-  # add_dependencies(viewer windows-setup windows-crash-logger)
-  add_dependencies(viewer windows-crash-logger)
 endif (LINUX)
 
-add_subdirectory(${VIEWER_PREFIX}newview)
-add_dependencies(viewer secondlife-bin)
-
-add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
+if (WINDOWS)
+    # cmake EXISTS requires an absolute path, see indra/cmake/Variables.cmake
+    if (EXISTS ${VIEWER_DIR}win_setup)
+      add_subdirectory(${VIEWER_DIR}win_setup)
+    endif (EXISTS ${VIEWER_DIR}win_setup)
+endif (WINDOWS)
 
 # sets the 'startup project' for debugging from visual studio.
 set_property(
@@ -98,7 +87,24 @@ if (USE_BUGSPLAT)
     endif (BUGSPLAT_DB)
 else (USE_BUGSPLAT)
     message(STATUS "Not building with BugSplat")
+    if (LINUX)
+      add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
+      add_dependencies(viewer linux-crash-logger-strip-target)
+    elseif (DARWIN)
+      add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
+      add_dependencies(viewer mac-crash-logger)
+    elseif (WINDOWS)
+      add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
+      # add_dependencies(viewer windows-setup windows-crash-logger)
+      add_dependencies(viewer windows-crash-logger)
+    endif (LINUX)
 endif (USE_BUGSPLAT)
+
+add_subdirectory(${VIEWER_PREFIX}newview)
+add_dependencies(viewer secondlife-bin)
+
+add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL)
+
 if (LL_TESTS)
   # Define after the custom targets are created so
   # individual apps can add themselves as dependencies
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index fd520d2c6f..40ff1263f2 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1808,9 +1808,12 @@ if (WINDOWS)
       media_plugin_libvlc
       media_plugin_example
       winmm_shim
-      windows-crash-logger
       )
 
+    if (NOT USE_BUGSPLAT)
+        LIST(APPEND COPY_INPUT_DEPENDENCIES windows-crash-logger)
+    endif (NOT USE_BUGSPLAT)
+
     if (ADDRESS_SIZE EQUAL 64)
         list(APPEND COPY_INPUT_DEPENDENCIES
             ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/vivoxsdk_x64.dll
@@ -1864,10 +1867,11 @@ if (WINDOWS)
       add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
     endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
 
-    add_dependencies(${VIEWER_BINARY_NAME}
-      SLPlugin
-      windows-crash-logger
-    )
+    add_dependencies(${VIEWER_BINARY_NAME} SLPlugin)
+
+    if (NOT USE_BUGSPLAT)
+        add_dependencies(${VIEWER_BINARY_NAME} windows-crash-logger)
+    endif (NOT USE_BUGSPLAT)
 
     # sets the 'working directory' for debugging from visual studio.
     # Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
@@ -2031,13 +2035,16 @@ if (LINUX)
   # These are the generated targets that are copied to package/
   set(COPY_INPUT_DEPENDENCIES
     ${VIEWER_BINARY_NAME}
-    linux-crash-logger
     SLPlugin
     media_plugin_gstreamer010
     media_plugin_libvlc
     llcommon
     )
 
+  if (NOT USE_BUGSPLAT)
+      LIST(APPEND COPY_INPUT_DEPENDENCIES linux-crash-logger)
+  endif (NOT USE_BUGSPLAT)
+
   add_custom_command(
       OUTPUT ${product}.tar.bz2
       COMMAND ${PYTHON_EXECUTABLE}
@@ -2162,8 +2169,11 @@ if (DARWIN)
       ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
     )
 
-  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef mac-crash-logger)
-  add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
+  add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef)
+
+  if (NOT USE_BUGSPLAT)
+      add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
+  endif (USE_BUGSPLAT)
 
   if (ENABLE_SIGNING)
       set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}")
@@ -2221,7 +2231,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
       list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/llplugin/slplugin/${CMAKE_CFG_INTDIR}")
       list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/mac_crash_logger/${CMAKE_CFG_INTDIR}")
       list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_BINARY_DIR}/media_plugins/gstreamer010/${CMAKE_CFG_INTDIR}")
-      set(VIEWER_EXE_GLOBS "'${product}' SLPlugin mac-crash-logger")
+      set(VIEWER_EXE_GLOBS "'${product}' SLPlugin")
       set(VIEWER_EXE_GLOBS "'${product}' mac-crash-logger")
       set(VIEWER_LIB_GLOB "*.dylib")
     endif (DARWIN)
-- 
cgit v1.2.3


From 4c525832cc7a32abce94823ac9c8ec2c4d510498 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 12 Jun 2019 08:49:59 -0400
Subject: remove old crash logger more

---
 indra/newview/llappviewermacosx.cpp | 9 +++++++--
 indra/newview/llappviewerwin32.cpp  | 6 +-----
 2 files changed, 8 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 9c2e6eadca..4a519b944b 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -241,7 +241,7 @@ bool LLAppViewerMacOSX::init()
 {
 	bool success = LLAppViewer::init();
     
-#if LL_SEND_CRASH_REPORTS
+#if !defined LL_BUGSPLAT && LL_SEND_CRASH_REPORTS
     if (success)
     {
         LLAppViewer* pApp = LLAppViewer::instance();
@@ -368,6 +368,7 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
 
 void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
 {
+#ifndef LL_BUGSPLAT
 	std::string command_str = "mac-crash-logger.app";
     
     std::stringstream pid_str;
@@ -379,6 +380,9 @@ void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
     LL_WARNS() << "about to launch mac-crash-logger" << pid_str.str()
                << " " << logdir << " " << appname << LL_ENDL;
     launchApplication(&command_str, &args);
+#else
+    LL_DEBUGS("InitOSX") << "using BugSplat instead of legacy crash logger" << LL_ENDL;
+#endif // ! LL_BUGSPLAT
 }
 
 std::string LLAppViewerMacOSX::generateSerialNumber()
@@ -390,7 +394,8 @@ std::string LLAppViewerMacOSX::generateSerialNumber()
 	CFStringRef serialNumber = NULL;
 	io_service_t    platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
 																 IOServiceMatching("IOPlatformExpertDevice"));
-	if (platformExpert) {
+	if (platformExpert)
+    {
 		serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
 																	 CFSTR(kIOPlatformSerialNumberKey),
 																	 kCFAllocatorDefault, 0);		
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 6a6cc225d4..235f7cc8ed 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -174,7 +174,7 @@ static void exceptionTerminateHandler()
     long *null_ptr;
     null_ptr = 0;
     *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
-	//LLAppViewer::handleViewerCrash();
+
 	// we've probably been killed-off before now, but...
 	gOldTerminateHandler(); // call old terminate() handler
 }
@@ -362,10 +362,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
 
 	viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
 
-#if LL_SEND_CRASH_REPORTS 
-	// ::SetUnhandledExceptionFilter(catchallCrashHandler); 
-#endif
-
 	// Set a debug info flag to indicate if multiple instances are running.
 	bool found_other_instance = !create_app_mutex();
 	gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance);
-- 
cgit v1.2.3


From 9627eddb102580703d6229bc6e827696dcb9e9d4 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 12 Jun 2019 08:51:01 -0400
Subject: document that old crash logger is not used in production builds

---
 indra/linux_crash_logger/README.txt | 3 +++
 indra/llcrashlogger/README.txt      | 3 +++
 indra/mac_crash_logger/README.txt   | 3 +++
 indra/win_crash_logger/README.txt   | 3 +++
 4 files changed, 12 insertions(+)
 create mode 100644 indra/linux_crash_logger/README.txt
 create mode 100644 indra/llcrashlogger/README.txt
 create mode 100644 indra/mac_crash_logger/README.txt
 create mode 100644 indra/win_crash_logger/README.txt

(limited to 'indra')

diff --git a/indra/linux_crash_logger/README.txt b/indra/linux_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/linux_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
diff --git a/indra/llcrashlogger/README.txt b/indra/llcrashlogger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/llcrashlogger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
diff --git a/indra/mac_crash_logger/README.txt b/indra/mac_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/mac_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
diff --git a/indra/win_crash_logger/README.txt b/indra/win_crash_logger/README.txt
new file mode 100644
index 0000000000..6932a8d9c3
--- /dev/null
+++ b/indra/win_crash_logger/README.txt
@@ -0,0 +1,3 @@
+This component is no longer used in Linden Lab builds.
+Change requests to support continued use by open source
+builds are welcome.
-- 
cgit v1.2.3


From 83ec9ebfbd602771dbc45c08fe203044b5ce3527 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 24 Sep 2019 10:15:20 -0400
Subject: log calls that modify the fatal error hook

---
 indra/llcommon/llerror.cpp            |  2 ++
 indra/llcommon/tests/llerror_test.cpp | 17 ++++++++++-------
 2 files changed, 12 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 5f3edf7f84..da68117ff5 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -723,11 +723,13 @@ namespace LLError
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		s->mFatalHook = fatal_hook;
+        LL_DEBUGS("FatalHook") << "set fatal hook to " << fatal_hook << LL_ENDL;
 	}
 
 	FatalHook getFatalHook()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+        LL_DEBUGS("FatalHook") << "read fatal hook " << s->mFatalHook << LL_ENDL;
 		return s->mFatalHook;
 	}
 
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 9895abc1f3..cdc2bf8c87 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -781,30 +781,33 @@ namespace tut
 		// proper cached, efficient lookup of filtering
 	void ErrorTestObject::test<15>()
 	{
-		LLError::setDefaultLevel(LLError::LEVEL_NONE);
+		LLError::setDefaultLevel(LLError::LEVEL_NONE); 
+
+        // Note that the setFatalHook in the ErrorTestData constructor
+        // increments the shouldLogCallCount
 
 		TestAlpha::doInfo();
 		ensure_message_count(0);
-		ensure_equals("first check", LLError::shouldLogCallCount(), 1);
+		ensure_equals("first check", LLError::shouldLogCallCount(), 2);
 		TestAlpha::doInfo();
 		ensure_message_count(0);
-		ensure_equals("second check", LLError::shouldLogCallCount(), 1);
+		ensure_equals("second check", LLError::shouldLogCallCount(), 2);
 
 		LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
 		TestAlpha::doInfo();
 		ensure_message_count(1);
-		ensure_equals("third check", LLError::shouldLogCallCount(), 2);
+		ensure_equals("third check", LLError::shouldLogCallCount(), 3);
 		TestAlpha::doInfo();
 		ensure_message_count(2);
-		ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
+		ensure_equals("fourth check", LLError::shouldLogCallCount(), 3);
 
 		LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
 		TestAlpha::doInfo();
 		ensure_message_count(2);
-		ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
+		ensure_equals("fifth check", LLError::shouldLogCallCount(), 4);
 		TestAlpha::doInfo();
 		ensure_message_count(2);
-		ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
+		ensure_equals("sixth check", LLError::shouldLogCallCount(), 4);
 	}
 
 	template<> template<>
-- 
cgit v1.2.3


From d0619f8e476c1c5118ae926dfe1746f1dda986d8 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 24 Sep 2019 14:27:21 -0400
Subject: improve fatal hook logging

---
 indra/llcommon/llerror.cpp    | 4 ++--
 indra/llcommon/llleap.cpp     | 2 ++
 indra/newview/llappviewer.cpp | 7 ++++++-
 3 files changed, 10 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index da68117ff5..df8443bd7a 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -723,13 +723,13 @@ namespace LLError
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		s->mFatalHook = fatal_hook;
-        LL_DEBUGS("FatalHook") << "set fatal hook to " << fatal_hook << LL_ENDL;
+        LL_DEBUGS("FatalHook") << "set fatal hook to " << reinterpret_cast<void*>(fatal_hook) << LL_ENDL;
 	}
 
 	FatalHook getFatalHook()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-        LL_DEBUGS("FatalHook") << "read fatal hook " << s->mFatalHook << LL_ENDL;
+        LL_DEBUGS("FatalHook") << "read fatal hook " << reinterpret_cast<void*>(s->mFatalHook) << LL_ENDL;
 		return s->mFatalHook;
 	}
 
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 161d25bc34..bb32c73d04 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -67,6 +67,7 @@ public:
         // this class or method name.
         mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
     {
+        LL_DEBUGS("FatalHook") << "previous fatal hook was " <<reinterpret_cast<void*>(mPrevFatalHook) << LL_ENDL;
         // Rule out unpopulated Params block
         if (! cparams.executable.isProvided())
         {
@@ -398,6 +399,7 @@ public:
         }
 
         // forward the call to the previous FatalHook, default to crashing if there isn't one
+        LL_DEBUGS("FatalHook") << "end" << LL_ENDL;
         return mPrevFatalHook ? mPrevFatalHook(error) : LLError::ERR_CRASH;
     }
 
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 35f9d7f4fd..9258d1a219 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2166,7 +2166,8 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
                                 ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
                                 );
-	LLError::setFatalHook(fatalErrorHook);
+
+    // TBD fatal hook belongs here
 
 	// Remove the last ".old" log file.
 	std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
@@ -2228,6 +2229,10 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	{
 		LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
 	}
+
+    // TBD - temporary location for fatal hook (should be above, but for now it logs...)
+    LLError::setFatalHook(fatalErrorHook);
+
 }
 
 bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
-- 
cgit v1.2.3


From 581b6fe5234110efa9c27751ed2c9e062ae8f248 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 24 Sep 2019 15:08:45 -0400
Subject: simplify function pointer logging

---
 indra/llcommon/llerror.cpp | 10 ++++++----
 indra/llcommon/llleap.cpp  |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index df8443bd7a..1f947a0a74 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -722,14 +722,16 @@ namespace LLError
 	void setFatalHook(const FatalHook& fatal_hook)
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+        LL_DEBUGS("FatalHook") << "set fatal hook to "(fatal_hook ? "non-null" : "null")
+                               << " was " << (s->mFatalHook ? "non-null" : "null")
+                               << LL_ENDL;
 		s->mFatalHook = fatal_hook;
-        LL_DEBUGS("FatalHook") << "set fatal hook to " << reinterpret_cast<void*>(fatal_hook) << LL_ENDL;
-	}
-
+    }
+    
 	FatalHook getFatalHook()
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-        LL_DEBUGS("FatalHook") << "read fatal hook " << reinterpret_cast<void*>(s->mFatalHook) << LL_ENDL;
+        LL_DEBUGS("FatalHook") << "read fatal hook was " << (s->mFatalHook ? "non-null" : "null") << LL_ENDL;
 		return s->mFatalHook;
 	}
 
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index bb32c73d04..1c0678e453 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -67,7 +67,7 @@ public:
         // this class or method name.
         mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
     {
-        LL_DEBUGS("FatalHook") << "previous fatal hook was " <<reinterpret_cast<void*>(mPrevFatalHook) << LL_ENDL;
+        LL_DEBUGS("FatalHook") << "previous fatal hook was " << (mPrevFatalHook ? "non-null" : "null") << LL_ENDL;
         // Rule out unpopulated Params block
         if (! cparams.executable.isProvided())
         {
-- 
cgit v1.2.3


From 092bf4220eeaea0ae7765ea3cb49f122fb3e3dff Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 24 Sep 2019 15:33:42 -0400
Subject: further simplify function pointer logging

---
 indra/llcommon/llerror.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 1f947a0a74..327c3ad537 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -722,7 +722,7 @@ namespace LLError
 	void setFatalHook(const FatalHook& fatal_hook)
 	{
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
-        LL_DEBUGS("FatalHook") << "set fatal hook to "(fatal_hook ? "non-null" : "null")
+        LL_DEBUGS("FatalHook") << "set fatal hook to " << (fatal_hook ? "non-null" : "null")
                                << " was " << (s->mFatalHook ? "non-null" : "null")
                                << LL_ENDL;
 		s->mFatalHook = fatal_hook;
-- 
cgit v1.2.3


From bc8b55e1f2d772a657e4f7affc8a6c7d20f2c2e4 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 25 Sep 2019 12:56:05 -0400
Subject: remove fatal error hook usage from LLLeap (potential races for
 multiple processes)

---
 indra/llcommon/llleap.cpp | 33 ---------------------------------
 1 file changed, 33 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 1c0678e453..8293c35516 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -59,7 +59,6 @@ public:
         // pump name -- so it should NOT need tweaking for uniqueness.
         mReplyPump(LLUUID::generateNewID().asString()),
         mExpect(0),
-        mPrevFatalHook(LLError::getFatalHook()),
         // Instantiate a distinct LLLeapListener for this plugin. (Every
         // plugin will want its own collection of managed listeners, etc.)
         // Pass it a callback to our connect() method, so it can send events
@@ -67,7 +66,6 @@ public:
         // this class or method name.
         mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2)))
     {
-        LL_DEBUGS("FatalHook") << "previous fatal hook was " << (mPrevFatalHook ? "non-null" : "null") << LL_ENDL;
         // Rule out unpopulated Params block
         if (! cparams.executable.isProvided())
         {
@@ -146,9 +144,6 @@ public:
         mStderrConnection = childerr.getPump()
             .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
 
-        // For our lifespan, intercept any LL_ERRS so we can notify plugin
-        LLError::setFatalHook(boost::bind(&LLLeapImpl::fatalHook, this, _1));
-
         // Send child a preliminary event reporting our own reply-pump name --
         // which would otherwise be pretty tricky to guess!
         wstdin(mReplyPump.getName(),
@@ -163,8 +158,6 @@ public:
     virtual ~LLLeapImpl()
     {
         LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
-        // Restore original FatalHook
-        LLError::setFatalHook(mPrevFatalHook);
     }
 
     // Listener for failed launch attempt
@@ -378,31 +371,6 @@ public:
         return false;
     }
 
-    LLError::ErrFatalHookResult fatalHook(const std::string& error)
-    {
-        // Notify plugin
-        LLSD event;
-        event["type"] = "error";
-        event["error"] = error;
-        mReplyPump.post(event);
-
-        // All the above really accomplished was to buffer the serialized
-        // event in our WritePipe. Have to pump mainloop a couple times to
-        // really write it out there... but time out in case we can't write.
-        LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
-        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-        LLSD nop;
-        F64 until = (LLTimer::getElapsedSeconds() + 2).value();
-        while (childin.size() && LLTimer::getElapsedSeconds() < until)
-        {
-            mainloop.post(nop);
-        }
-
-        // forward the call to the previous FatalHook, default to crashing if there isn't one
-        LL_DEBUGS("FatalHook") << "end" << LL_ENDL;
-        return mPrevFatalHook ? mPrevFatalHook(error) : LLError::ERR_CRASH;
-    }
-
 private:
     /// We always want to listen on mReplyPump with wstdin(); under some
     /// circumstances we'll also echo other LLEventPumps to the plugin.
@@ -423,7 +391,6 @@ private:
         mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
     boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
     LLProcess::ReadPipe::size_type mExpect;
-    LLError::FatalHook mPrevFatalHook;
     boost::scoped_ptr<LLLeapListener> mListener;
 };
 
-- 
cgit v1.2.3


From 79801c717de5de6b86b45eadf61b352c9951f61e Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 25 Sep 2019 12:57:51 -0400
Subject: fix warning about mismatched condition

---
 indra/newview/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 40ff1263f2..ab6b8c9c6e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2173,7 +2173,7 @@ if (DARWIN)
 
   if (NOT USE_BUGSPLAT)
       add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
-  endif (USE_BUGSPLAT)
+  endif (NOT USE_BUGSPLAT)
 
   if (ENABLE_SIGNING)
       set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}")
-- 
cgit v1.2.3


From 66970f2a8c048647242887eb3f0c7fd974a303ac Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 25 Sep 2019 12:58:43 -0400
Subject: fix spurious per-frame warning about signal handlers in Windows

---
 indra/newview/llappviewerwin32.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 235f7cc8ed..63de9af566 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -798,7 +798,7 @@ bool LLAppViewerWin32::beingDebugged()
 
 bool LLAppViewerWin32::restoreErrorTrap()
 {	
-	return false;
+	return true; // we don't check for handler collisions on windows, so just say they're ok
 }
 
 void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
-- 
cgit v1.2.3


From a45ca18ff8160bc3edc584d6516ca019dd6c6275 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 25 Sep 2019 12:59:20 -0400
Subject: when using bugsplat, do not catch SIGABRT; also, fix signal setting
 in Mac (broken macro)

---
 indra/llcommon/llapp.cpp            | 5 +++++
 indra/newview/llappviewer.cpp       | 2 +-
 indra/newview/llappviewermacosx.cpp | 9 +++++----
 3 files changed, 11 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 34c969437b..27960371f1 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -779,7 +779,9 @@ void setup_signals()
 	act.sa_flags = SA_SIGINFO;
 
 	// Synchronous signals
+#   ifndef LL_BUGSPLAT
 	sigaction(SIGABRT, &act, NULL);
+#   endif
 	sigaction(SIGALRM, &act, NULL);
 	sigaction(SIGBUS, &act, NULL);
 	sigaction(SIGFPE, &act, NULL);
@@ -816,7 +818,9 @@ void clear_signals()
 	act.sa_flags = SA_SIGINFO;
 
 	// Synchronous signals
+#   ifndef LL_BUGSPLAT
 	sigaction(SIGABRT, &act, NULL);
+#   endif
 	sigaction(SIGALRM, &act, NULL);
 	sigaction(SIGBUS, &act, NULL);
 	sigaction(SIGFPE, &act, NULL);
@@ -869,6 +873,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 
 		return;
 	case SIGABRT:
+        // Note that this handler is not set for SIGABRT when using Bugsplat
 		// Abort just results in termination of the app, no funky error handling.
 		if (LLApp::sLogInSignal)
 		{
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9258d1a219..8009a9c117 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2231,8 +2231,8 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	}
 
     // TBD - temporary location for fatal hook (should be above, but for now it logs...)
+    LL_DEBUGS("FatalHook") << "initial setting of default fatalhook" << LL_ENDL;
     LLError::setFatalHook(fatalErrorHook);
-
 }
 
 bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 4a519b944b..efa1da054c 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -333,11 +333,12 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
 	
 	unsigned int reset_count = 0;
 	
-#define SET_SIG(S) 	sigaction(SIGABRT, &act, &old_act); \
-					if(act.sa_sigaction != old_act.sa_sigaction) \
-						++reset_count;
+#define SET_SIG(SIGNAL) sigaction(SIGNAL, &act, &old_act); \
+                        if(act.sa_sigaction != old_act.sa_sigaction) ++reset_count;
 	// Synchronous signals
-	SET_SIG(SIGABRT)
+#   ifndef LL_BUGSPLAT
+	SET_SIG(SIGABRT) // let bugsplat catch this
+#   endif        
 	SET_SIG(SIGALRM)
 	SET_SIG(SIGBUS)
 	SET_SIG(SIGFPE)
-- 
cgit v1.2.3


From de5c07ec50d192e5a34cf710e2d1ed0c1127932f Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 7 Oct 2019 10:50:32 -0400
Subject: do not build the old crash logger when using bugsplat

---
 indra/CMakeLists.txt | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra')

diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 4dd2dcc2e9..bd3bcd1173 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -46,7 +46,10 @@ endif (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
 
 add_custom_target(viewer)
 
+if (NOT USE_BUGSPLAT)
 add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
+endif (NOT USE_BUGSPLAT)
+
 add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
 add_subdirectory(${LIBS_OPEN_PREFIX}llui)
 add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
-- 
cgit v1.2.3


From 2961fea6933621fc7c8ebc692d4c517d4aa93096 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 8 Oct 2019 10:15:19 -0400
Subject: Rename uploaded log file to get Bugsplat to server as text/plain

---
 indra/newview/llappdelegate-objc.mm | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 30bfe1f439..ccab9173a9 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -301,9 +301,13 @@ struct AttachmentInfo
 
     // We "happen to know" that info[0].basename is "SecondLife.old" -- due to
     // the fact that BugsplatMac only notices a crash during the viewer run
-    // following the crash. Replace .old with .log to reduce confusion.
+    // following the crash. 
+    // The Bugsplat service doesn't respect the MIME type above when returning
+    // the log data to a browser, so take this opportunity to rename the file
+    // from <base>.old to <base>_log.txt
     info[0].basename = 
-        boost::filesystem::path(info[0].pathname).stem().string() + ".log";
+        boost::filesystem::path(info[0].pathname).stem().string() + "_log.txt";
+    infos("attachmentsForBugsplatStartupManager attaching log " + info[0].basename);
 
     NSMutableArray *attachments = [[NSMutableArray alloc] init];
 
-- 
cgit v1.2.3


From 1082a886ce8ffe4a23943b8513356a509373f03c Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 8 Oct 2019 10:15:47 -0400
Subject: tag initialization and bugsplat related logging

---
 indra/newview/llappviewermacosx.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index efa1da054c..999a475f8b 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -91,7 +91,7 @@ void constructViewer()
 	// Set the working dir to <bundle>/Contents/Resources
 	if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1)
 	{
-		LL_WARNS() << "Could not change directory to "
+		LL_WARNS("InitOSX") << "Could not change directory to "
 				<< gDirUtilp->getAppRODataDir() << ": " << strerror(errno)
 				<< LL_ENDL;
 	}
@@ -109,7 +109,7 @@ bool initViewer()
 	bool ok = gViewerAppPtr->init();
 	if(!ok)
 	{
-		LL_WARNS() << "Application init failed." << LL_ENDL;
+		LL_WARNS("InitOSX") << "Application init failed." << LL_ENDL;
 	}
 	else if (!gHandleSLURL.empty())
 	{
@@ -172,7 +172,7 @@ class CrashMetadataSingleton: public CrashMetadata, public LLSingleton<CrashMeta
     std::string get_metadata(const LLSD& info, const LLSD::String& key) const
     {
         std::string data(info[key].asString());
-        LL_INFOS() << "  " << key << "='" << data << "'" << LL_ENDL;
+        LL_INFOS("Bugsplat") << "  " << key << "='" << data << "'" << LL_ENDL;
         return data;
     }
 };
@@ -188,17 +188,17 @@ CrashMetadataSingleton::CrashMetadataSingleton()
     LLSD info;
     if (! static_file.is_open())
     {
-        LL_WARNS() << "Can't open '" << staticDebugPathname
+        LL_WARNS("Bugsplat") << "Can't open '" << staticDebugPathname
                    << "'; no metadata about previous run" << LL_ENDL;
     }
     else if (! LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED))
     {
-        LL_WARNS() << "Can't parse '" << staticDebugPathname
+        LL_WARNS("Bugsplat") << "Can't parse '" << staticDebugPathname
                    << "'; no metadata about previous run" << LL_ENDL;
     }
     else
     {
-        LL_INFOS() << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL;
+        LL_INFOS("Bugsplat") << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL;
         logFilePathname      = get_metadata(info, "SLLog");
         userSettingsPathname = get_metadata(info, "SettingsFilename");
         OSInfo               = get_metadata(info, "OSInfo");
@@ -218,7 +218,7 @@ CrashMetadata& CrashMetadata_instance()
 
 void infos(const std::string& message)
 {
-    LL_INFOS() << message << LL_ENDL;
+    LL_INFOS("InitOSX", "Bugsplat") << message << LL_ENDL;
 }
 
 int main( int argc, char **argv ) 
-- 
cgit v1.2.3


From 675842a2d4680e5e3bbbfba3db6fc183362083ea Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Fri, 13 Dec 2019 12:20:50 -0500
Subject: clarify crash logger at startup

---
 indra/newview/llappviewermacosx.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 999a475f8b..5a0fe6ba0c 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -81,7 +81,8 @@ static void exceptionTerminateHandler()
     long *null_ptr;
     null_ptr = 0;
     *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
-	//LLAppViewer::handleViewerCrash();
+	LLAppViewer::handleViewerCrash();
+
 	// we've probably been killed-off before now, but...
 	gOldTerminateHandler(); // call old terminate() handler
 }
@@ -99,7 +100,7 @@ void constructViewer()
 	gViewerAppPtr = new LLAppViewerMacOSX();
 
     // install unexpected exception handler
-	gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
+	//gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
 
 	gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
 }
@@ -241,14 +242,11 @@ bool LLAppViewerMacOSX::init()
 {
 	bool success = LLAppViewer::init();
     
-#if !defined LL_BUGSPLAT && LL_SEND_CRASH_REPORTS
     if (success)
     {
         LLAppViewer* pApp = LLAppViewer::instance();
         pApp->initCrashReporting();
     }
-#endif
-    
     return success;
 }
 
@@ -369,7 +367,10 @@ bool LLAppViewerMacOSX::restoreErrorTrap()
 
 void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
 {
-#ifndef LL_BUGSPLAT
+#if defined LL_BUGSPLAT
+    LL_DEBUGS("InitOSX", "Bugsplat") << "using BugSplat crash logger" << LL_ENDL;
+#elif LL_SEND_CRASH_REPORTS
+    LL_DEBUGS("InitOSX") << "Initializing legacy crash logger" << LL_ENDL;
 	std::string command_str = "mac-crash-logger.app";
     
     std::stringstream pid_str;
@@ -382,7 +383,7 @@ void LLAppViewerMacOSX::initCrashReporting(bool reportFreeze)
                << " " << logdir << " " << appname << LL_ENDL;
     launchApplication(&command_str, &args);
 #else
-    LL_DEBUGS("InitOSX") << "using BugSplat instead of legacy crash logger" << LL_ENDL;
+    LL_DEBUGS("InitOSX") << "No crash logger enabled" << LL_ENDL;    
 #endif // ! LL_BUGSPLAT
 }
 
-- 
cgit v1.2.3


From 5056ba6daafce402a5db6d2b75dceb20ed452e1d Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 16 Dec 2019 17:09:42 -0500
Subject: remove unused exception handler

---
 indra/newview/llappviewermacosx.cpp | 19 -------------------
 1 file changed, 19 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index 5a0fe6ba0c..784a104573 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -68,25 +68,9 @@ namespace
 	int gArgC;
 	char** gArgV;
 	LLAppViewerMacOSX* gViewerAppPtr = NULL;
-
-    void (*gOldTerminateHandler)() = NULL;
     std::string gHandleSLURL;
 }
 
-static void exceptionTerminateHandler()
-{
-	// reinstall default terminate() handler in case we re-terminate.
-	if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);
-	// treat this like a regular viewer crash, with nice stacktrace etc.
-    long *null_ptr;
-    null_ptr = 0;
-    *null_ptr = 0xDEADBEEF; //Force an exception that will trigger breakpad.
-	LLAppViewer::handleViewerCrash();
-
-	// we've probably been killed-off before now, but...
-	gOldTerminateHandler(); // call old terminate() handler
-}
-
 void constructViewer()
 {
 	// Set the working dir to <bundle>/Contents/Resources
@@ -99,9 +83,6 @@ void constructViewer()
 
 	gViewerAppPtr = new LLAppViewerMacOSX();
 
-    // install unexpected exception handler
-	//gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
-
 	gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
 }
 
-- 
cgit v1.2.3


From 17598f936bb6b099f21fc32aa80b68258cdfd0b9 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Mon, 16 Dec 2019 17:09:58 -0500
Subject: remove unused legacy crash logger

---
 indra/newview/viewer_manifest.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index a403760670..861c2120d8 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1060,10 +1060,10 @@ class DarwinManifest(ViewerManifest):
 
                 # our apps
                 executable_path = {}
-                for app_bld_dir, app in (("mac_crash_logger", "mac-crash-logger.app"),
-                                         # plugin launcher
-                                         (os.path.join("llplugin", "slplugin"), "SLPlugin.app"),
-                                         ):
+                embedded_apps = [ (os.path.join("llplugin", "slplugin"), "SLPlugin.app") ]
+                if bugsplat_db:
+                    embedded_apps.append(("mac_crash_logger", "mac-crash-logger.app"))
+                for app_bld_dir, app in embedded_apps:
                     self.path2basename(os.path.join(os.pardir,
                                                     app_bld_dir, self.args['configuration']),
                                        app)
-- 
cgit v1.2.3


From 68105d9f06aea69980cf0402f00da0e2be450dd2 Mon Sep 17 00:00:00 2001
From: Brad Kittenbrink <brad@lindenlab.com>
Date: Thu, 2 Apr 2020 10:55:31 -0700
Subject: Fixed -Wstring-plus-int related errors for compatibility with
 Xcode-11.4

---
 indra/llcommon/llsdutil.cpp        | 2 +-
 indra/newview/llcommandhandler.cpp | 2 +-
 indra/newview/llxmlrpclistener.cpp | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 9d00395c0a..859d2eb567 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -332,7 +332,7 @@ struct Data
     const char* name;
 } typedata[] =
 {
-#define def(type) { LLSD::type, #type + 4 }
+#define def(type) { LLSD::type, &#type[4] }
     def(TypeUndefined),
     def(TypeBoolean),
     def(TypeInteger),
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 76d965b1f1..23e2271eae 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -222,7 +222,7 @@ struct symbol_info
 
 #define ent(SYMBOL)										\
 	{													\
-		#SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */	\
+		&#SYMBOL[28], /* skip "LLCommandHandler::UNTRUSTED_" prefix */	\
 		SYMBOL											\
 	}
 
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 7bc8af4a0b..7db2b88951 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -100,7 +100,7 @@ public:
     {
         // from curl.h
 // skip the "CURLE_" prefix for each of these strings
-#define def(sym) (mMap[sym] = #sym + 6)
+#define def(sym) (mMap[sym] = &#sym[6])
         def(CURLE_OK);
         def(CURLE_UNSUPPORTED_PROTOCOL);    /* 1 */
         def(CURLE_FAILED_INIT);             /* 2 */
-- 
cgit v1.2.3


From 9834955be072aeac3f886de2eaf1e075000108c7 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 16 Jun 2020 14:41:28 -0400
Subject: SL-10297: remove mac-crash-logger from viewer-manifest, require the
 bugsplat library on Mac

---
 indra/cmake/bugsplat.cmake       | 4 ++--
 indra/newview/viewer_manifest.py | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake
index 749ea05403..5f5cc51f63 100644
--- a/indra/cmake/bugsplat.cmake
+++ b/indra/cmake/bugsplat.cmake
@@ -13,8 +13,8 @@ if (USE_BUGSPLAT)
                 ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib
                 )
         elseif (DARWIN)
-            find_library(BUGSPLAT_LIBRARIES BugsplatMac
-                PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
+            find_library(BUGSPLAT_LIBRARIES BugsplatMac REQUIRED
+                NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
         else (WINDOWS)
             message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF")
         endif (WINDOWS)
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index ff0781991e..7cecfec1eb 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1063,7 +1063,7 @@ class DarwinManifest(ViewerManifest):
                 # our apps
                 executable_path = {}
                 embedded_apps = [ (os.path.join("llplugin", "slplugin"), "SLPlugin.app") ]
-                if bugsplat_db:
+                if not bugsplat_db:
                     embedded_apps.append(("mac_crash_logger", "mac-crash-logger.app"))
                 for app_bld_dir, app in embedded_apps:
                     self.path2basename(os.path.join(os.pardir,
-- 
cgit v1.2.3


From 4e1db3b048478168eeda457cc74c43053adebc38 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 17 Jul 2020 00:24:32 +0300
Subject: SL-13443 Reduce stalls on writing cache to file

---
 indra/newview/llvocache.cpp | 51 ++++++++++++++++++---------------------------
 1 file changed, 20 insertions(+), 31 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 07660ca6ac..689eeee0e3 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -347,36 +347,24 @@ void LLVOCacheEntry::dump() const
 
 BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
 {
-	BOOL success;
-	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		S32 size = mDP.getBufferSize();
-		success = check_write(apr_file, (void*)&size, sizeof(S32));
-	
-		if(success)
-		{
-			success = check_write(apr_file, (void*)mBuffer, size);
-		}
-	}
-
-	return success ;
+    static const S32 data_buffer_size = 6 * sizeof(S32);
+    static U8 data_buffer[data_buffer_size];
+    S32 size = mDP.getBufferSize();
+
+    memcpy(data_buffer, &mLocalID, sizeof(U32));
+    memcpy(data_buffer + sizeof(U32), &mCRC, sizeof(U32));
+    memcpy(data_buffer + (2 * sizeof(U32)), &mHitCount, sizeof(S32));
+    memcpy(data_buffer + (3 * sizeof(U32)), &mDupeCount, sizeof(S32));
+    memcpy(data_buffer + (4 * sizeof(U32)), &mCRCChangeCount, sizeof(S32));
+    memcpy(data_buffer + (5 * sizeof(U32)), &size, sizeof(S32));
+
+    BOOL success = check_write(apr_file, (void*)data_buffer, data_buffer_size);
+    if (success)
+    {
+        success = check_write(apr_file, (void*)mBuffer, size);
+    }
+
+    return success;
 }
 
 //static 
@@ -1537,7 +1525,8 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
 		{
 			S32 num_entries = cache_entry_map.size() ;
 			success = check_write(&apr_file, &num_entries, sizeof(S32));
-	
+
+			// This can have a lot of entries, so might be better to dump them into buffer first and write in one go.
 			for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
 			{
 				if(!removal_enabled || iter->second->isValid())
-- 
cgit v1.2.3


From ffa9fc3c4756438d25f92bd30380b176e860d9b9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 20 Aug 2020 23:21:57 +0300
Subject: SL-13638 Optimize cache writing and reading

Cache writing and reading happens in main thread and can cause significant drop in performance
---
 indra/newview/llvocache.cpp | 125 ++++++++++++++++++++++++++------------------
 indra/newview/llvocache.h   |   2 +-
 2 files changed, 74 insertions(+), 53 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 689eeee0e3..5ebc65405f 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -44,6 +44,9 @@ F32 LLVOCacheEntry::sFrontPixelThreshold = 1.0f;
 F32 LLVOCacheEntry::sRearPixelThreshold = 1.0f;
 BOOL LLVOCachePartition::sNeedsOcclusionCheck = FALSE;
 
+const S32 ENTRY_HEADER_SIZE = 6 * sizeof(S32);
+const S32 MAX_ENTRY_BODY_SIZE = 10000;
+
 BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) 
 {
 	return apr_file->read(src, n_bytes) == n_bytes ;
@@ -111,32 +114,22 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 {
 	S32 size = -1;
 	BOOL success;
+    static U8 data_buffer[ENTRY_HEADER_SIZE];
 
 	mDP.assignBuffer(mBuffer, 0);
-	
-	success = check_read(apr_file, &mLocalID, sizeof(U32));
-	if(success)
-	{
-		success = check_read(apr_file, &mCRC, sizeof(U32));
-	}
-	if(success)
-	{
-		success = check_read(apr_file, &mHitCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_read(apr_file, &mDupeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_read(apr_file, &mCRCChangeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_read(apr_file, &size, sizeof(S32));
+
+    success = check_read(apr_file, (void *)data_buffer, ENTRY_HEADER_SIZE);
+    if (success)
+    {
+        memcpy(&mLocalID, data_buffer, sizeof(U32));
+        memcpy(&mCRC, data_buffer + sizeof(U32), sizeof(U32));
+        memcpy(&mHitCount, data_buffer + (2 * sizeof(U32)), sizeof(S32));
+        memcpy(&mDupeCount, data_buffer + (3 * sizeof(U32)), sizeof(S32));
+        memcpy(&mCRCChangeCount, data_buffer + (4 * sizeof(U32)), sizeof(S32));
+        memcpy(&size, data_buffer + (5 * sizeof(U32)), sizeof(S32));
 
 		// Corruption in the cache entries
-		if ((size > 10000) || (size < 1))
+		if ((size > MAX_ENTRY_BODY_SIZE) || (size < 1))
 		{
 			// We've got a bogus size, skip reading it.
 			// We won't bother seeking, because the rest of this file
@@ -345,26 +338,25 @@ void LLVOCacheEntry::dump() const
 		<< LL_ENDL;
 }
 
-BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
+S32 LLVOCacheEntry::writeToBuffer(U8 *data_buffer) const
 {
-    static const S32 data_buffer_size = 6 * sizeof(S32);
-    static U8 data_buffer[data_buffer_size];
     S32 size = mDP.getBufferSize();
 
+    if (size > MAX_ENTRY_BODY_SIZE)
+    {
+        LL_WARNS() << "Failed to write entry with size above allowed limit: " << size << LL_ENDL;
+        return 0;
+    }
+
     memcpy(data_buffer, &mLocalID, sizeof(U32));
     memcpy(data_buffer + sizeof(U32), &mCRC, sizeof(U32));
     memcpy(data_buffer + (2 * sizeof(U32)), &mHitCount, sizeof(S32));
     memcpy(data_buffer + (3 * sizeof(U32)), &mDupeCount, sizeof(S32));
     memcpy(data_buffer + (4 * sizeof(U32)), &mCRCChangeCount, sizeof(S32));
     memcpy(data_buffer + (5 * sizeof(U32)), &size, sizeof(S32));
+    memcpy(data_buffer + ENTRY_HEADER_SIZE, (void*)mBuffer, size);
 
-    BOOL success = check_write(apr_file, (void*)data_buffer, data_buffer_size);
-    if (success)
-    {
-        success = check_write(apr_file, (void*)mBuffer, size);
-    }
-
-    return success;
+    return ENTRY_HEADER_SIZE + size;
 }
 
 //static 
@@ -1393,11 +1385,11 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
 	bool success = true ;
 	{
 		std::string filename;
+		LLUUID cache_id;
 		getObjectCacheFilename(handle, filename);
 		LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
 	
-		LLUUID cache_id ;
-		success = check_read(&apr_file, cache_id.mData, UUID_BYTES) ;
+		success = check_read(&apr_file, cache_id.mData, UUID_BYTES);
 	
 		if(success)
 		{		
@@ -1409,7 +1401,7 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
 
 			if(success)
 			{
-				S32 num_entries;
+				S32 num_entries;  // if removal was enabled during write num_entries might be wrong
 				success = check_read(&apr_file, &num_entries, sizeof(S32)) ;
 	
 				if(success)
@@ -1516,28 +1508,57 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
 	{
 		std::string filename;
 		getObjectCacheFilename(handle, filename);
-		LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp);
+		LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY|APR_TRUNCATE, mLocalAPRFilePoolp);
 	
-		success = check_write(&apr_file, (void*)id.mData, UUID_BYTES) ;
-
+		success = check_write(&apr_file, (void*)id.mData, UUID_BYTES);
 	
 		if(success)
 		{
-			S32 num_entries = cache_entry_map.size() ;
+			S32 num_entries = cache_entry_map.size(); // if removal is enabled num_entries might be wrong
 			success = check_write(&apr_file, &num_entries, sizeof(S32));
-
-			// This can have a lot of entries, so might be better to dump them into buffer first and write in one go.
-			for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
-			{
-				if(!removal_enabled || iter->second->isValid())
-				{
-					success = iter->second->writeToFile(&apr_file) ;
-					if(!success)
-					{
-						break;
-					}
-				}
-			}
+            if (success)
+            {
+                const S32 buffer_size = 32768; //should be large enough for couple MAX_ENTRY_BODY_SIZE
+                U8 data_buffer[buffer_size]; // generaly entries are fairly small, so collect them and drop onto disk in one go
+                S32 size_in_buffer = 0;
+
+                // This can have a lot of entries, so might be better to dump them into buffer first and write in one go.
+                for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
+                {
+                    if (!removal_enabled || iter->second->isValid())
+                    {
+                        S32 size = iter->second->writeToBuffer(data_buffer + size_in_buffer);
+
+                        if (size > ENTRY_HEADER_SIZE) // body is minimum of 1
+                        {
+                            size_in_buffer += size;
+                        }
+                        else
+                        {
+                            success = false;
+                            break;
+                        }
+
+                        // Make sure we have space in buffer for next element
+                        if (buffer_size - size_in_buffer < MAX_ENTRY_BODY_SIZE + ENTRY_HEADER_SIZE)
+                        {
+                            success = check_write(&apr_file, (void*)data_buffer, size_in_buffer);
+                            size_in_buffer = 0;
+                            if (!success)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (success && size_in_buffer > 0)
+                {
+                    // final write
+                    success = check_write(&apr_file, (void*)data_buffer, size_in_buffer);
+                    size_in_buffer = 0;
+                }
+            }
 		}
 	}
 
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 6c95541c11..dd6afd6b85 100644
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -106,7 +106,7 @@ public:
 	F32 getSceneContribution() const             { return mSceneContrib;}
 
 	void dump() const;
-	BOOL writeToFile(LLAPRFile* apr_file) const;
+	S32 writeToBuffer(U8 *data_buffer) const;
 	LLDataPackerBinaryBuffer *getDP();
 	void recordHit();
 	void recordDupe() { mDupeCount++; }
-- 
cgit v1.2.3


From 0048a4cf18f958591c5e4f9ec829e4ecdc642926 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 21 Aug 2020 15:20:23 +0300
Subject:  SL-13823  FIXED "Settings" are not shown in Inventory filter message

---
 indra/newview/llinventoryfilter.cpp            | 12 ++++++++++++
 indra/newview/skins/default/xui/en/strings.xml |  1 +
 2 files changed, 13 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 745b953996..8f18de0210 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -1230,6 +1230,18 @@ const std::string& LLInventoryFilter::getFilterText()
 		filtered_by_all_types = FALSE;
 	}
 
+	if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS))
+	{
+		filtered_types +=  LLTrans::getString("Settings");
+		filtered_by_type = TRUE;
+		num_filter_types++;
+	}
+	else
+	{
+		not_filtered_types +=  LLTrans::getString("Settings");
+		filtered_by_all_types = FALSE;
+	}
+
 	if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
 		&& filtered_by_type
 		&& !filtered_by_all_types)
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bfac6aeb7..c9ea423a20 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2415,6 +2415,7 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="Scripts"       value=" Scripts," />
 	<string name="Sounds"        value=" Sounds," />
 	<string name="Textures"      value=" Textures," />
+	<string name="Settings"      value=" Settings," />
 	<string name="Snapshots"     value=" Snapshots," />
 	<string name="No Filters"    value="No " />
 	<string name="Since Logoff"  value=" - Since Logoff" />
-- 
cgit v1.2.3


From fc74a2df6364889149b5ebd0638839582fda358f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 21 Aug 2020 16:40:53 +0300
Subject: SL-13824 Remove notification when joining a group

---
 indra/newview/llviewermessage.cpp                    |  1 -
 indra/newview/skins/default/xui/en/notifications.xml | 12 ------------
 2 files changed, 13 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 06a8ebbe89..e78ace061e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -777,7 +777,6 @@ void response_group_invitation_coro(std::string url, LLUUID group_id, bool notif
             LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL;
             if (notify_and_update)
             {
-                LLNotificationsUtil::add("JoinGroupSuccess");
                 gAgent.sendAgentDataUpdateRequest();
 
                 LLGroupMgr::getInstance()->clearGroupData(group_id);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 32ae56e3af..fa1c15c411 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1022,18 +1022,6 @@ The group no longer has open enrollment.
        yestext="OK"/>
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="JoinGroupSuccess"
-   type="alertmodal">
-You have been added to the group
-    <tag>group_id</tag>
-    <tag>success</tag>
-    <usetemplate
-       name="okbutton"
-       yestext="OK"/>
-  </notification>
-  
   <notification
    icon="alertmodal.tga"
    name="JoinGroupInsufficientFunds"
-- 
cgit v1.2.3


From 7897f909c4879d2f092f7310d59d78b5deebe634 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 25 Aug 2020 15:18:40 +0300
Subject: SL-13843 FIXED URL gets changed when opened in the internal web
 browse

---
 indra/llcommon/lluri.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index 9942bc0cf8..22711a83d2 100644
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -276,7 +276,7 @@ std::string LLURI::escapePathAndData(const std::string &str)
             std::string fragment;
 
             size_t fragment_pos = str.find('#');
-            if (fragment_pos != std::string::npos)
+            if ((fragment_pos != std::string::npos) && (fragment_pos > delim_pos))
             {
                 query = str.substr(path_size, fragment_pos - path_size);
                 fragment = str.substr(fragment_pos);
-- 
cgit v1.2.3


From 6a9c89fd62ee458dff4f2ade76d44947b99e472a Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 25 Aug 2020 11:59:27 -0400
Subject: SL-10297 do not package win_crash_logger executable if using BugSplat

---
 indra/newview/viewer_manifest.py | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 2105b419e7..c636f1d910 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -673,10 +673,11 @@ class WindowsManifest(ViewerManifest):
                 self.path("libvlccore.dll")
                 self.path("plugins/")
 
-        # pull in the crash logger from other projects
-        # tag:"crash-logger" here as a cue to the exporter
-        self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
-                  dst="win_crash_logger.exe")
+        if not bugsplat_db: # don't include the win_crash_logger if we are using BugSplat
+            # pull in the crash logger from other projects
+            # tag:"crash-logger" here as a cue to the exporter
+            self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
+                      dst="win_crash_logger.exe")
 
         if not self.is_packaging_viewer():
             self.package_file = "copied_deps"    
-- 
cgit v1.2.3


From 50509a56b6714a1a075463a02e5a853d97a3c461 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Tue, 25 Aug 2020 12:35:04 -0400
Subject: SL-10297 fix check for bugsplat

---
 indra/newview/viewer_manifest.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index c636f1d910..6161a8b413 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -673,7 +673,7 @@ class WindowsManifest(ViewerManifest):
                 self.path("libvlccore.dll")
                 self.path("plugins/")
 
-        if not bugsplat_db: # don't include the win_crash_logger if we are using BugSplat
+        if not self.args.get('bugsplat'): # don't include the win_crash_logger if we are using BugSplat
             # pull in the crash logger from other projects
             # tag:"crash-logger" here as a cue to the exporter
             self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
-- 
cgit v1.2.3


From 34786ac22129aac372eeb1e73b6baac6bfad644e Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 26 Aug 2020 12:26:07 +0300
Subject: SL-13824 Remove notification when both joining a group and leaving a
 group

---
 indra/newview/llviewermessage.cpp                    | 9 +++++++++
 indra/newview/skins/default/xui/en/notifications.xml | 7 -------
 2 files changed, 9 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e78ace061e..9c56766d0d 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5036,6 +5036,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
 		// notification was specified using the new mechanism, so we can just handle it here
 		std::string notificationID;
 		msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
+
+		//SL-13824 skip notification when both joining a group and leaving a group
+		//remove this after server stops sending these messages  
+		if (notificationID == "JoinGroupSuccess" ||
+			notificationID == "GroupDepart")
+		{
+			return true;
+		}
+
 		if (!LLNotifications::getInstance()->templateExists(notificationID))
 		{
 			return false;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fa1c15c411..d141cfc313 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4214,13 +4214,6 @@ Leave Group?
      yestext="OK"/>
   </notification>
 
-  <notification
-   icon="notify.tga"
-   name="GroupDepart"
-   type="notify">
-You have left the group &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;.
-    <tag>group</tag>
-  </notification>
 
   <notification
    icon="alertmodal.tga"
-- 
cgit v1.2.3


From 4e4564dcf31766469ccf41e0eef82bc234fda72c Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 26 Aug 2020 09:53:38 -0400
Subject: SL-10297 fix MSVC warning controls (merge error)

---
 indra/test/test.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index b16fcb84d6..748d042631 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -58,7 +58,8 @@
 #include <gtest/gtest.h>
 #endif
 
-#if LL_WINDOWS
+#if LL_MSVC
+#pragma warning (push)
 #pragma warning (disable : 4702) // warning C4702: unreachable code
 #endif
 #include <boost/iostreams/tee.hpp>
-- 
cgit v1.2.3


From 1aa140d3affa28d85a41d55f2566a19fb9d2cff5 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 26 Aug 2020 15:33:20 -0400
Subject: SL-10297 fix MSVC unreachable code warning

---
 indra/test/test.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'indra')

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 748d042631..55dad94bc1 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -77,8 +77,14 @@
 
 LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message)
 {
+#if LL_MSVC
+#pragma warning (push)
+#pragma warning (disable : 4702) // warning C4702: unreachable code
 	tut::fail("fatal error message: " + message);
     return LLError::ERR_DO_NOT_CRASH;
+#if LL_MSVC
+#pragma warning (pop)
+#endif
 }
 
 namespace tut
-- 
cgit v1.2.3


From 6007475c87d3edbb023cc64bb097d33e6c04dfd4 Mon Sep 17 00:00:00 2001
From: Oz Linden <oz@lindenlab.com>
Date: Wed, 26 Aug 2020 16:37:23 -0400
Subject: SL-10297 fix MSVC unreachable code warning (for real)

---
 indra/test/test.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra')

diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 55dad94bc1..571f502861 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -80,6 +80,7 @@ LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message)
 #if LL_MSVC
 #pragma warning (push)
 #pragma warning (disable : 4702) // warning C4702: unreachable code
+#endif
 	tut::fail("fatal error message: " + message);
     return LLError::ERR_DO_NOT_CRASH;
 #if LL_MSVC
-- 
cgit v1.2.3


From f3fbb042ccef2fdb1d3f38ec48c7724706e732d7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 27 Aug 2020 21:49:51 +0300
Subject: SL-12585 Decrease space for time field

---
 indra/newview/skins/default/xui/en/panel_status_bar.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index ada980cda1..9023d68ea9 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -35,7 +35,7 @@
     </panel.string>
   <panel
 	 height="18"
-	 left="-458"
+	 left="-398"
 	 top="0"
 	 width="120"
 	 follows="right|top"
@@ -75,7 +75,7 @@
   </panel>
   <panel
     height="18"
-    left="-458"
+    left="-398"
     width="185"
     top="1"
     follows="right|top" 
@@ -142,7 +142,7 @@
      left_pad="0"
      name="TimeText"
      tool_tip="Current time (Pacific)"
-     width="145">
+     width="85">
         24:00 AM PST
     </text>
     <icon
-- 
cgit v1.2.3


From 9527199b0a0ca6b1089a05eef13674ebab5e8637 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 28 Aug 2020 16:26:30 +0300
Subject: SL-13877 'Classified' accordion does not disappear after deleting all
 Classifieds

---
 indra/newview/llpanelpicks.cpp | 45 ++++++++++++++++++++++++++++++------------
 indra/newview/llpanelpicks.h   |  1 +
 2 files changed, 33 insertions(+), 13 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index c39df3fe8b..8bb776bda6 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -472,19 +472,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
 		mNoClassifieds = !mClassifiedsList->size();
 	}
 
-	bool no_data = mNoPicks && mNoClassifieds;
-	mNoItemsLabel->setVisible(no_data);
-	if (no_data)
-	{
-		if(getAvatarId() == gAgentID)
-		{
-			mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText"));
-		}
-		else
-		{
-			mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText"));
-		}
-	}
+    updateNoItemsLabel();
 }
 
 LLPickItem* LLPanelPicks::getSelectedPickItem()
@@ -713,6 +701,13 @@ bool LLPanelPicks::callbackDeletePick(const LLSD& notification, const LLSD& resp
 	{
 		LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]);
 		mPicksList->removeItemByValue(pick_value);
+        
+        mNoPicks = !mPicksList->size();
+        if (mNoPicks)
+        {
+            showAccordion("tab_picks", false);
+        }
+        updateNoItemsLabel();
 	}
 	updateButtons();
 	return false;
@@ -727,6 +722,13 @@ bool LLPanelPicks::callbackDeleteClassified(const LLSD& notification, const LLSD
 	{
 		LLAvatarPropertiesProcessor::instance().sendClassifiedDelete(value[CLASSIFIED_ID]);
 		mClassifiedsList->removeItemByValue(value);
+
+        mNoClassifieds = !mClassifiedsList->size();
+        if (mNoClassifieds)
+        {
+            showAccordion("tab_classifieds", false);
+        }
+        updateNoItemsLabel();
 	}
 	updateButtons();
 	return false;
@@ -840,6 +842,23 @@ void LLPanelPicks::updateButtons()
 	}
 }
 
+void LLPanelPicks::updateNoItemsLabel()
+{
+    bool no_data = mNoPicks && mNoClassifieds;
+    mNoItemsLabel->setVisible(no_data);
+    if (no_data)
+    {
+        if (getAvatarId() == gAgentID)
+        {
+            mNoItemsLabel->setValue(LLTrans::getString("NoPicksClassifiedsText"));
+        }
+        else
+        {
+            mNoItemsLabel->setValue(LLTrans::getString("NoAvatarPicksClassifiedsText"));
+        }
+    }
+}
+
 void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
 {
 	mProfilePanel = profile_panel;
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 3bb7413ac3..fd7688b99d 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -87,6 +87,7 @@ public:
 
 protected:
 	/*virtual*/void updateButtons();
+	void updateNoItemsLabel();
 
 private:
 	void onClickDelete();
-- 
cgit v1.2.3


From 18566c502398e0e449717a06b1ffae3966e55522 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 31 Aug 2020 21:27:37 +0300
Subject: SL-13852 Add visibility options to inventory search results

---
 indra/llui/lllineeditor.h                          |   3 +
 indra/llui/llsearcheditor.cpp                      |  22 +++++-
 indra/llui/llsearcheditor.h                        |  20 ++++-
 indra/newview/llfolderviewmodelinventory.h         |   1 +
 indra/newview/llinventoryfilter.cpp                |  85 ++++++++++++++++++++-
 indra/newview/llinventoryfilter.h                  |  17 ++++-
 indra/newview/llpanelmaininventory.cpp             |  35 +++++++++
 indra/newview/llpanelmaininventory.h               |   2 +
 .../icons/Inv_Toolbar_SearchVisibility.png         | Bin 0 -> 756 bytes
 indra/newview/skins/default/textures/textures.xml  |   3 +
 .../widgets/TextField_Search_Highlight.png         | Bin 0 -> 16287 bytes
 .../xui/en/menu_inventory_search_visibility.xml    |  44 +++++++++++
 .../skins/default/xui/en/panel_main_inventory.xml  |  40 ++++++----
 .../skins/default/xui/en/widgets/filter_editor.xml |   4 +-
 .../skins/default/xui/en/widgets/search_editor.xml |   4 +-
 15 files changed, 258 insertions(+), 22 deletions(-)
 create mode 100644 indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
 create mode 100644 indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
 create mode 100644 indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml

(limited to 'indra')

diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index aa5779d45f..f84625bea7 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -283,6 +283,9 @@ public:
 
 	void			resetContextMenu() { setContextMenu(NULL); };
 
+	void			setBgImage(LLPointer<LLUIImage> image) { mBgImage = image; }
+	void			setBgImageFocused(LLPointer<LLUIImage> image) { mBgImageFocused = image; }
+
 private:
 	// private helper methods
 
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index 1fdd05a11c..bafeef41fb 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -34,7 +34,11 @@
 LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 :	LLUICtrl(p),
 	mSearchButton(NULL),
-	mClearButton(NULL)
+	mClearButton(NULL),
+	mEditorImage(p.background_image),
+	mEditorImageFocused(p.background_image_focused),
+	mEditorSearchImage(p.background_image_highlight),
+	mHighlightTextField(p.highlight_text_field)
 {
 	S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
 	S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
@@ -57,6 +61,8 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 	// Set up line editor.
 	LLLineEditor::Params line_editor_params(p);
 	line_editor_params.name("filter edit box");
+	line_editor_params.background_image(p.background_image);
+	line_editor_params.background_image_focused(p.background_image_focused);
 	line_editor_params.rect(getLocalRect());
 	line_editor_params.follows.flags(FOLLOWS_ALL);
 	line_editor_params.text_pad_left(text_pad_left);
@@ -104,6 +110,20 @@ void LLSearchEditor::draw()
 	if (mClearButton)
 		mClearButton->setVisible(!mSearchEditor->getWText().empty());
 
+	if (mHighlightTextField)
+	{	
+		if (!mSearchEditor->getWText().empty())
+		{
+			mSearchEditor->setBgImage(mEditorSearchImage);
+			mSearchEditor->setBgImageFocused(mEditorSearchImage);
+		}
+		else
+		{
+			mSearchEditor->setBgImage(mEditorImage);
+			mSearchEditor->setBgImageFocused(mEditorImageFocused);
+		}
+	}
+
 	LLUICtrl::draw();
 }
 
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index 3b12868225..c0f3c1d60c 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -47,14 +47,23 @@ public:
 		Optional<LLButton::Params>	search_button, 
 									clear_button;
 		Optional<bool>				search_button_visible, 
-									clear_button_visible;
+									clear_button_visible,
+									highlight_text_field;
 		Optional<commit_callback_t> keystroke_callback;
 
+		Optional<LLUIImage*>		background_image,
+									background_image_focused,
+									background_image_highlight;
+
 		Params()
 		:	search_button("search_button"),
 			search_button_visible("search_button_visible"),
 			clear_button("clear_button"), 
-			clear_button_visible("clear_button_visible")
+			clear_button_visible("clear_button_visible"),
+			highlight_text_field("highlight_text_field"),
+			background_image("background_image"),
+			background_image_focused("background_image_focused"),
+			background_image_highlight("background_image_highlight")
 		{}
 	};
 
@@ -93,6 +102,13 @@ protected:
 	LLLineEditor* mSearchEditor;
 	LLButton* mSearchButton;
 	LLButton* mClearButton;
+
+	LLPointer<LLUIImage> mEditorImage;
+	LLPointer<LLUIImage> mEditorImageFocused;
+	LLPointer<LLUIImage> mEditorSearchImage;
+	LLPointer<LLUIImage> mEditorSearchImageFocused;
+
+	bool mHighlightTextField;
 };
 
 #endif  // LL_SEARCHEDITOR_H
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 06a908cccc..51b98339c4 100644
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -45,6 +45,7 @@ public:
 	virtual LLFolderType::EType getPreferredType() const = 0;
 	virtual void showProperties(void) = 0;
 	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual.
+	virtual BOOL isAgentInventory() const { return FALSE; }
 	virtual BOOL isUpToDate() const = 0;
 	virtual bool hasChildren() const = 0;
 	virtual LLInventoryType::EType getInventoryType() const = 0;
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 8f18de0210..1b99c90d5c 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -63,7 +63,8 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
 	mPermissions(p.permissions),
 	mFilterTypes(p.types),
 	mFilterUUID(p.uuid),
-	mFilterLinks(p.links)
+	mFilterLinks(p.links),
+	mSearchVisibility(0xffffFFFFffffFFFFULL)
 {
 }
 
@@ -154,6 +155,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
 	passed = passed && checkAgainstPermissions(listener);
 	passed = passed && checkAgainstFilterLinks(listener);
 	passed = passed && checkAgainstCreator(listener);
+	passed = passed && checkAgainstSearchVisibility(listener);
 
 	return passed;
 }
@@ -550,6 +552,27 @@ bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory
 	}
 }
 
+bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const
+{
+	if (!listener || !hasFilterString()) return TRUE;
+
+	const LLUUID object_id = listener->getUUID();
+	const LLInventoryObject *object = gInventory.getObject(object_id);
+	if (!object) return TRUE;
+
+	const BOOL is_link = object->getIsLinkType();
+	if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0))
+		return FALSE;
+
+	if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
+		return FALSE;
+
+	if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
+		return FALSE;
+
+	return TRUE;
+}
+
 const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
 {
 	return mFilterSubString;
@@ -718,6 +741,61 @@ void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_list
     }
 }
 
+
+void LLInventoryFilter::toggleSearchVisibilityLinks()
+{
+	bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS;
+	if (hide_links)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_LINKS;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
+void LLInventoryFilter::toggleSearchVisibilityTrash()
+{
+	bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH;
+	if (hide_trash)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_TRASH;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
+void LLInventoryFilter::toggleSearchVisibilityLibrary()
+{
+	bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY;
+	if (hide_library)
+	{
+		mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY;
+	}
+	else
+	{
+		mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY;
+	}
+
+	if (hasFilterString())
+	{
+		setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
+	}
+}
+
 void LLInventoryFilter::setFilterNoMarketplaceFolder()
 {
     mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
@@ -1349,6 +1427,11 @@ U64 LLInventoryFilter::getFilterSettingsTypes() const
     return mFilterOps.mFilterSettingsTypes;
 }
 
+U64 LLInventoryFilter::getSearchVisibilityTypes() const
+{
+	return mFilterOps.mSearchVisibility;
+}
+
 bool LLInventoryFilter::hasFilterString() const
 {
 	return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index be02ee3623..caba8315c4 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -99,6 +99,14 @@ public:
 		FILTERCREATOR_OTHERS
 	};
 
+	enum ESearchVisibility
+	{
+		VISIBILITY_NONE = 0,
+		VISIBILITY_TRASH = 0x1 << 0,
+		VISIBILITY_LIBRARY = 0x1 << 1,
+		VISIBILITY_LINKS	= 0x1 << 2
+	};
+
 	struct FilterOps
 	{
 		struct DateRange : public LLInitParam::Block<DateRange>
@@ -154,6 +162,7 @@ public:
 						mFilterWearableTypes,
                         mFilterSettingsTypes, // for _SETTINGS
 						mFilterLinks,
+						mSearchVisibility,
 						mFilterCategoryTypes; // For _CATEGORY
 		LLUUID      	mFilterUUID; 		  // for UUID
 
@@ -193,7 +202,8 @@ public:
 	U64 				getFilterObjectTypes() const;
 	U64					getFilterCategoryTypes() const;
 	U64					getFilterWearableTypes() const;
-    U64                 getFilterSettingsTypes() const;
+	U64					getFilterSettingsTypes() const;
+	U64					getSearchVisibilityTypes() const;
 
 	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const;
 	void 				setFilterObjectTypes(U64 types);
@@ -213,6 +223,10 @@ public:
 	ESearchType			getSearchType() { return mSearchType; }
 	void 				setFilterCreator(EFilterCreatorType type);
 
+	void				toggleSearchVisibilityLinks();
+	void				toggleSearchVisibilityTrash();
+	void				toggleSearchVisibilityLibrary();
+
 	void 				setFilterSubString(const std::string& string);
 	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;
 	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; } 
@@ -309,6 +323,7 @@ private:
 	bool 				checkAgainstPermissions(const LLInventoryItem* item) const;
 	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const;
 	bool 				checkAgainstCreator(const class LLFolderViewModelItemInventory* listener) const;
+	bool				checkAgainstSearchVisibility(const class LLFolderViewModelItemInventory* listener) const;
 	bool				checkAgainstClipboard(const LLUUID& object_id) const;
 
 	FilterOps				mFilterOps;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 02cd22c307..d24440ebbd 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -115,6 +115,7 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
 	  mSavedFolderState(NULL),
 	  mFilterText(""),
 	  mMenuGearDefault(NULL),
+	  mMenuVisibility(NULL),
 	  mMenuAddHandle(),
 	  mNeedUploadCost(true)
 {
@@ -228,6 +229,7 @@ BOOL LLPanelMainInventory::postBuild()
 	}
 
 	mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
+	mVisibilityMenuButton = getChild<LLMenuButton>("options_visibility_btn");
 
 	initListCommandsHandlers();
 
@@ -1164,6 +1166,9 @@ void LLPanelMainInventory::initListCommandsHandlers()
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mMenuAddHandle = menu->getHandle();
 
+	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mVisibilityMenuButton->setMenu(mMenuVisibility);
+
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
 }
@@ -1353,6 +1358,21 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		}
 		LLFloaterReg::showInstance("linkreplace", params);
 	}
+
+	if (command_name == "toggle_search_trash")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityTrash();
+	}
+
+	if (command_name == "toggle_search_library")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityLibrary();
+	}
+
+	if (command_name == "include_links")
+	{
+		mActivePanel->getFilter().toggleSearchVisibilityLinks();
+	}		
 }
 
 void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
@@ -1498,6 +1518,21 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
 		return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
 	}
 
+	if (command_name == "toggle_search_trash")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0;
+	}
+
+	if (command_name == "toggle_search_library")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0;
+	}
+
+	if (command_name == "include_links")
+	{
+		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0;	
+	}	
+
 	return FALSE;
 }
 
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index a6bdee233d..5211aa0c92 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -169,7 +169,9 @@ protected:
 private:
 	LLDragAndDropButton*		mTrashButton;
 	LLToggleableMenu*			mMenuGearDefault;
+	LLToggleableMenu*			mMenuVisibility;
 	LLMenuButton*				mGearMenuButton;
+	LLMenuButton*				mVisibilityMenuButton;
 	LLHandle<LLView>			mMenuAddHandle;
 
 	bool						mNeedUploadCost;
diff --git a/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png b/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
new file mode 100644
index 0000000000..048da25c92
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 7325d836d2..1302edda7a 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -333,6 +333,8 @@ with the same filename but different name
   <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
   <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
   <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
+
+  <texture name="Inv_Toolbar_SearchVisibility" file_name="icons/Inv_Toolbar_SearchVisibility.png" preload="false" />
   
   <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
   <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
@@ -648,6 +650,7 @@ with the same filename but different name
   <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+  <texture name="TextField_Search_Highlight" file_name="widgets/TextField_Search_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
 
 
   <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
new file mode 100644
index 0000000000..e3944289c6
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png differ
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml b/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
new file mode 100644
index 0000000000..46193f4a7a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ bottom="806"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_search_visibility"
+ visible="false">
+  <menu_item_check
+   label="Search Trash"
+   layout="topleft"
+   name="search_trash">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="toggle_search_trash" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="toggle_search_trash" />
+  </menu_item_check>
+  <menu_item_check
+   label="Search Library"
+   layout="topleft"
+   name="search_library">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="toggle_search_library" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="toggle_search_library" />
+  </menu_item_check>
+  <menu_item_separator
+   layout="topleft" />
+  <menu_item_check
+   label="Include links"
+   layout="topleft"
+   name="include_links">
+    <on_click
+     function="Inventory.GearDefault.Custom.Action"
+     parameter="include_links" />
+    <on_check
+     function="Inventory.GearDefault.Check"
+     parameter="include_links" />         
+  </menu_item_check>    
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index d77fbdec0a..2ff58035ed 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -32,30 +32,20 @@
     		 left="12"
 		     name="ItemcountText"
 		     font="SansSerifMedium"
-		     text_color="EmphasisColor"
+		     text_color="InventoryItemLinkColor"
 		     use_ellipses="true"
 		     top_pad="0"
 		     width="300">
     Items:
   </text>
-  <filter_editor
-   text_pad_left="10"
-   follows="left|top|right"
+  <combo_box
    height="23"
-   label="Enter search text"
    layout="topleft"
    left="10"
-   max_length_chars="300"
-   name="inventory search editor"
    top="18"
-   width="208" />
-  <combo_box
-   height="23"
-   layout="topleft"
-   left_pad="4"
    name="search_type"
-   follows="top|right"
-   width="90">
+   follows="top|left"
+   width="88">
     <item
      label="Name"
      name="Name"
@@ -72,7 +62,27 @@
      label="UUID"
      name="UUID"
      value="search_by_UUID"/>
-    </combo_box>
+  </combo_box>
+  <menu_button
+   follows="top|left"
+   tool_tip="Show search visibility options"
+   height="23"
+   image_overlay="Inv_Toolbar_SearchVisibility"
+   layout="topleft"
+   left_pad="3"
+   name="options_visibility_btn"
+   width="31" />
+  <filter_editor
+   text_pad_left="10"
+   follows="left|top|right"
+   height="23"
+   label="Enter search text"
+   layout="topleft"
+   left_pad="3"
+   max_length_chars="300"
+   highlight_text_field="true"
+   name="inventory search editor"
+   width="177" />
   <tab_container
      follows="all"
      halign="center"
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index 2cc4abdd30..1c4822b8d5 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -6,9 +6,11 @@
   text_pad_left="7"
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
+  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active">
+  background_image_focused="TextField_Search_Active"
+  background_image_highlight="TextField_Search_Highlight">
   <search_button label=""
     top_pad="4"
     left_pad="4"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index faa0404b35..dc5a07bf4f 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,9 +7,11 @@
   text_pad_right="6" 
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
+  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active" >
+  background_image_focused="TextField_Search_Active"
+  background_image_highlight="TextField_Search_Highlight">
   <search_button 
     top_pad="4"
     left_pad="4" 
-- 
cgit v1.2.3


From bac27a9d74bc8eb55699aedcf957ba7532ef02c5 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 1 Sep 2020 20:03:03 +0300
Subject: SL-13852 Show menu below the button

---
 indra/newview/llpanelmaininventory.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra')

diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d24440ebbd..bcbf92a488 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1168,6 +1168,7 @@ void LLPanelMainInventory::initListCommandsHandlers()
 
 	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mVisibilityMenuButton->setMenu(mMenuVisibility);
+	mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT);
 
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
-- 
cgit v1.2.3


From 7e2e2503c5fb57736844bdad0f309d2d49ee86b2 Mon Sep 17 00:00:00 2001
From: maxim_productengine <mnikolenko@productengine.com>
Date: Mon, 17 Feb 2020 17:43:00 +0200
Subject: =?UTF-8?q?SL-11867=20Show=20=E2=80=9CUnable=20to=20buy=E2=80=9D?=
 =?UTF-8?q?=20message=20via=20notification?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 indra/newview/llfloaterbuycurrency.cpp             | 37 +++----------------
 .../skins/default/xui/da/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/de/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/en/floater_buy_currency.xml  | 42 +++-------------------
 .../newview/skins/default/xui/en/notifications.xml | 12 +++++++
 .../skins/default/xui/es/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/fr/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/it/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/ja/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/pl/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/pt/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/ru/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/tr/floater_buy_currency.xml  |  5 ++-
 .../skins/default/xui/zh/floater_buy_currency.xml  |  5 ++-
 14 files changed, 43 insertions(+), 103 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 91436e52fe..25348474a1 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -74,7 +74,6 @@ public:
 
 	void onClickBuy();
 	void onClickCancel();
-	void onClickErrorWeb();
 };
 
 LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
@@ -132,7 +131,6 @@ BOOL LLFloaterBuyCurrencyUI::postBuild()
 	
 	getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this));
 	getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this));
-	getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickErrorWeb, this));
 	
 	center();
 	
@@ -173,7 +171,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 	// hide most widgets - we'll turn them on as needed next
 	getChildView("info_buying")->setVisible(FALSE);
-	getChildView("info_cannot_buy")->setVisible(FALSE);
 	getChildView("info_need_more")->setVisible(FALSE);	
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
@@ -183,32 +180,16 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	if (hasError)
 	{
 		// display an error from the server
-		getChildView("normal_background")->setVisible(FALSE);
-		getChildView("error_background")->setVisible(TRUE);
-		getChildView("info_cannot_buy")->setVisible(TRUE);
-		getChildView("cannot_buy_message")->setVisible(TRUE);
-		getChildView("balance_label")->setVisible(FALSE);
-		getChildView("balance_amount")->setVisible(FALSE);
-		getChildView("buying_label")->setVisible(FALSE);
-		getChildView("buying_amount")->setVisible(FALSE);
-		getChildView("total_label")->setVisible(FALSE);
-		getChildView("total_amount")->setVisible(FALSE);
-
-        LLTextBox* message = getChild<LLTextBox>("cannot_buy_message");
-        if (message)
-		{
-			message->setText(mManager.errorMessage());
-		}
-
-		getChildView("error_web")->setVisible( !mManager.errorURI().empty());
+		LLSD args;
+		args["TITLE"] = getString("info_cannot_buy");
+		args["MESSAGE"] = mManager.errorMessage();
+		LLNotificationsUtil::add("CouldNotBuyCurrency", args);
+		closeFloater();
 	}
 	else
 	{
 		// display the main Buy L$ interface
 		getChildView("normal_background")->setVisible(TRUE);
-		getChildView("error_background")->setVisible(FALSE);
-		getChildView("cannot_buy_message")->setVisible(FALSE);
-		getChildView("error_web")->setVisible(FALSE);
 
 		if (mHasTarget)
 		{
@@ -278,14 +259,6 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
 	LLStatusBar::sendMoneyBalanceRequest();
 }
 
-void LLFloaterBuyCurrencyUI::onClickErrorWeb()
-{
-	LLWeb::loadURL(mManager.errorURI());
-	closeFloater();
-	// Update L$ balance
-	LLStatusBar::sendMoneyBalanceRequest();
-}
-
 // static
 void LLFloaterBuyCurrency::buyCurrency()
 {
diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index 3c0428b2b0..b7ac181dd4 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -60,8 +60,7 @@ objektet.
 	</text>
 	<button label="Køb nu" name="buy_btn"/>
 	<button label="Annullér" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+  <floater.string name="info_cannot_buy">
 		Kan ikke købe
-	</text>
-	<button label="Fortsæt til web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index 65926c088c..eb94df1cad 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Jetzt kaufen" name="buy_btn"/>
 	<button label="Abbrechen" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+  <floater.string name="info_cannot_buy">
 		Kaufabbruch
-	</text>
-	<button label="Weiter zur Kontoseite" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 553c5d51d0..061af1b67c 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -13,6 +13,10 @@
      name="buy_currency">
         Buy L$ [LINDENS] for approx. [LOCALAMOUNT]
     </floater.string>
+    <floater.string
+     name="info_cannot_buy">
+        Unable to Buy
+    </floater.string>
     <icon
      height="215"
      image_name="Linden_Dollar_Background"
@@ -286,42 +290,4 @@ Re-enter amount to see the latest exchange rate.
      left_pad="10"
      name="cancel_btn"
      width="90"/>
-    <icon
-     height="215"
-     image_name="Linden_Dollar_Alert"
-     layout="topleft"
-     left="0"
-     name="error_background"
-     top="15"
-     use_draw_context_alpha="false"
-     width="350"/>
-    <text
-     type="string"
-     font="SansSerifHuge"
-     left="165"
-     width="360"
-     height="25"
-     top="25"
-     name="info_cannot_buy">
-        Unable to Buy
-    </text>
-     <text
-      type="string"
-      width="176"
-      height="125"
-      top="60"
-      left="165"
-      word_wrap="true"
-      follows="bottom|right"
-      name="cannot_buy_message">
-     </text>
-     <button
-      follows="bottom|left"
-      height="20"
-      label="Continue to the Web"
-      layout="topleft"
-      left="170"
-      name="error_web"
-      top="200"
-      width="160"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d141cfc313..3228603f45 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1329,6 +1329,18 @@ There was a problem uploading a report screenshot due to the following reason: [
 You must agree to the Second Life Terms and Conditions, Privacy Policy, and Terms of Service to continue logging into [SECOND_LIFE].
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="CouldNotBuyCurrency"
+   type="alertmodal">
+[TITLE]
+[MESSAGE]
+   <tag>fail</tag>
+   <usetemplate
+     name="okbutton"
+     yestext="OK"/>
+  </notification>
+  
   <notification
    icon="alertmodal.tga"
    name="CouldNotPutOnOutfit"
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index dbff3fcf0e..086150dd57 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,8 +60,7 @@ no el objeto.
 	</text>
 	<button label="Comprar ahora" name="buy_btn"/>
 	<button label="Cancelar" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="150" font="SansSerifBig">
+	<floater.string name="info_cannot_buy">
 		No se pudo hacer la compra
-	</text>
-	<button label="Ir a la web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index c295172abf..55b0d1825a 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,8 +60,7 @@ le Lindex...
 	</text>
 	<button label="Acheter" name="buy_btn"/>
 	<button label="Annuler" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="160" width="200">
+	<floater.string name="info_cannot_buy" left="160" width="200">
 		Achat impossible
-	</text>
-	<button label="Accéder au Web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 53a2057455..522d26373e 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,8 +60,7 @@ l&apos;oggetto.
 	</text>
 	<button label="Acquista" name="buy_btn"/>
 	<button label="Annulla" name="cancel_btn"/>
-	<text name="info_cannot_buy" left="160" font="SansSerifBig">
+	<floater.string name="info_cannot_buy" left="160" font="SansSerifBig">
 		Non in grado di acquistare
-	</text>
-	<button label="Continua sul Web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index a472f163e3..ac2db917cc 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="購入する" name="buy_btn"/>
 	<button label="取り消し" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		購入できません
-	</text>
-	<button label="Web サイトに移動" name="error_web" width="140"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index 72167e0d3c..a1d703a15a 100644
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -50,8 +50,7 @@
 	</text>
 	<button label="Kup teraz" name="buy_btn" />
 	<button label="Anuluj" name="cancel_btn" />
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Nie można kupić
-	</text>
-	<button label="Odwiedź stronę WWW" name="error_web" />
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index 513400954b..c740b90472 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Comprar já!" name="buy_btn"/>
 	<button label="Fechar" name="cancel_btn"/>
-	<text name="info_cannot_buy" font="SansSerifBig">
+	<floater.string name="info_cannot_buy">
 		Transação incompleta
-	</text>
-	<button label="Prosseguir para a web" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index 87e8bd524e..ef55ce58d4 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Приобрести" name="buy_btn"/>
 	<button label="Отмена" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Нельзя купить
-	</text>
-	<button label="Продолжить в Интернете" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index d90985dcff..33c4b2287f 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="Şimdi Satın Al" name="buy_btn"/>
 	<button label="İptal" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		Satın Alınamıyor
-	</text>
-	<button label="Web&apos;e devam et" name="error_web"/>
+	</floater.string>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
index fcf2800728..41c8c26ccc 100644
--- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
@@ -59,8 +59,7 @@
 	</text>
 	<button label="立即購買" name="buy_btn"/>
 	<button label="取消" name="cancel_btn"/>
-	<text name="info_cannot_buy">
+	<floater.string name="info_cannot_buy">
 		無法購買
-	</text>
-	<button label="繼續到網頁" name="error_web"/>
+	</floater.string>
 </floater>
-- 
cgit v1.2.3


From 38c80cfab4e5a17932c128276715977b31dcc7c4 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 2 Sep 2020 23:58:27 +0300
Subject: SL-8225 Do not sit or autopilot to 'zero' global coordinates

Also significantly increases autopilot flight precision
---
 indra/newview/llagent.cpp                        | 61 ++++++++++++++++++++----
 indra/newview/llviewermenu.cpp                   | 43 ++++++++++-------
 indra/newview/skins/default/xui/en/menu_land.xml |  2 +
 3 files changed, 79 insertions(+), 27 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f3df79fb6b..1527f19189 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -108,7 +108,8 @@ const U8 AGENT_STATE_EDITING =  0x10;
 // Autopilot constants
 const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f;			// meters
 const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f;	// meters
-const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f;		// seconds
+const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK = 1.5f;		// seconds
+const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY = 2.5f;		// seconds. Flying is less presize, needs a bit more time
 
 const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;
 const F64 CHAT_AGE_FAST_RATE = 3.0;
@@ -1518,6 +1519,12 @@ void LLAgent::startAutoPilotGlobal(
 	{
 		return;
 	}
+
+    if (target_global.isExactlyZero())
+    {
+        LL_WARNS() << "Canceling attempt to start autopilot towards invalid position" << LL_ENDL;
+        return;
+    }
 	
 	// Are there any pending callbacks from previous auto pilot requests?
 	if (mAutoPilotFinishedCallback)
@@ -1733,7 +1740,16 @@ void LLAgent::autoPilot(F32 *delta_yaw)
 		if (target_dist >= mAutoPilotTargetDist)
 		{
 			mAutoPilotNoProgressFrameCount++;
-			if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)
+            bool out_of_time = false;
+            if (getFlying())
+            {
+                out_of_time = mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS_FLY * gFPSClamped;
+            }
+            else
+            {
+                out_of_time = mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS_WALK * gFPSClamped;
+            }
+			if (out_of_time)
 			{
 				stopAutoPilot();
 				return;
@@ -1782,7 +1798,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)
 		F32 slow_distance;
 		if (getFlying())
 		{
-			slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f);
+			slow_distance = llmax(8.f, mAutoPilotStopDistance + 5.f);
 		}
 		else
 		{
@@ -1826,14 +1842,41 @@ void LLAgent::autoPilot(F32 *delta_yaw)
 		}
 		else if (mAutoPilotTargetDist > mAutoPilotStopDistance)
 		{
-			// walking/flying slow
+            // walking/flying slow
+            U32 movement_flag = 0;
+
 			if (at * direction > 0.9f)
 			{
-				setControlFlags(AGENT_CONTROL_AT_POS);
-			}
-			else if (at * direction < -0.9f)
-			{
-				setControlFlags(AGENT_CONTROL_AT_NEG);
+                movement_flag = AGENT_CONTROL_AT_POS;
+            }
+            else if (at * direction < -0.9f)
+            {
+                movement_flag = AGENT_CONTROL_AT_NEG;
+            }
+
+            if (getFlying())
+            {
+                // flying is too fast and has high inertia, artificially slow it down
+                // Don't update flags too often, server might not react
+                static U64 last_time_microsec = 0;
+                U64 time_microsec = LLTimer::getTotalTime();
+                U64 delta = time_microsec - last_time_microsec;
+                // fly during ~0-40 ms, stop during ~40-250 ms
+                if (delta > 250000) // 250ms
+                {
+                    // reset even if !movement_flag
+                    last_time_microsec = time_microsec;
+                }
+                else if (delta > 40000) // 40 ms
+                {
+                    clearControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_AT_POS);
+                    movement_flag = 0;
+                }
+            }
+
+            if (movement_flag)
+            {
+                setControlFlags(movement_flag);
 			}
 		}
 
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b6c7be2ed3..b333b94462 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4067,25 +4067,31 @@ void near_sit_down_point(BOOL success, void *)
 
 class LLLandSit : public view_listener_t
 {
-	bool handleEvent(const LLSD& userdata)
-	{
-		gAgent.standUp();
-		LLViewerParcelMgr::getInstance()->deselectLand();
+    bool handleEvent(const LLSD& userdata)
+    {
+        LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
 
-		LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
-		
-		LLQuaternion target_rot;
-		if (isAgentAvatarValid())
-		{
-			target_rot = gAgentAvatarp->getRotation();
-		}
-		else
-		{
-			target_rot = gAgent.getFrameAgent().getQuaternion();
-		}
-		gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f);
-		return true;
-	}
+        LLQuaternion target_rot;
+        if (isAgentAvatarValid())
+        {
+            target_rot = gAgentAvatarp->getRotation();
+        }
+        else
+        {
+            target_rot = gAgent.getFrameAgent().getQuaternion();
+        }
+        gAgent.startAutoPilotGlobal(posGlobal, "Sit", &target_rot, near_sit_down_point, NULL, 0.7f);
+        return true;
+    }
+};
+
+class LLLandCanSit : public view_listener_t
+{
+    bool handleEvent(const LLSD& userdata)
+    {
+        LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal;
+        return !posGlobal.isExactlyZero(); // valid position, not beyond draw distance
+    }
 };
 
 //-------------------------------------------------------------------
@@ -9289,6 +9295,7 @@ void initialize_menus()
 	// Land pie menu
 	view_listener_t::addMenu(new LLLandBuild(), "Land.Build");
 	view_listener_t::addMenu(new LLLandSit(), "Land.Sit");
+    view_listener_t::addMenu(new LLLandCanSit(), "Land.CanSit");
 	view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass");
 	view_listener_t::addMenu(new LLLandEdit(), "Land.Edit");
 
diff --git a/indra/newview/skins/default/xui/en/menu_land.xml b/indra/newview/skins/default/xui/en/menu_land.xml
index 2ad5cbbe95..1ce0d65b3e 100644
--- a/indra/newview/skins/default/xui/en/menu_land.xml
+++ b/indra/newview/skins/default/xui/en/menu_land.xml
@@ -18,6 +18,8 @@
     <menu_item_call
      label="Sit Here"
      name="Sit Here">
+        <menu_item_call.on_enable
+         function="Land.CanSit" />
         <menu_item_call.on_click
          function="Land.Sit" />
     </menu_item_call>
-- 
cgit v1.2.3


From f150600ffb17232bfa88a6225aab437460fc9520 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 3 Sep 2020 17:29:06 +0300
Subject: SL-13814 Clarify dialog for insufficient L$ balance

---
 indra/newview/llcurrencyuimanager.cpp              |   7 +-
 indra/newview/llfloaterbuycurrency.cpp             |  61 +-
 .../skins/default/xui/en/floater_buy_currency.xml  | 624 ++++++++++++---------
 3 files changed, 416 insertions(+), 276 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index df94e337da..cd7332c4d4 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -454,7 +454,7 @@ void LLCurrencyUIManager::Impl::updateUI()
 		
 		if (!mUserEnteredCurrencyBuy)
 		{
-			if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
+			if (mUserCurrencyBuy == 0)
 			{
 				lindenAmount->setText(LLStringUtil::null);
 			}
@@ -467,8 +467,9 @@ void LLCurrencyUIManager::Impl::updateUI()
 		}
 	}
 
-	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", getLocalEstimate());
-	mPanel.getChildView("currency_est")->setVisible( hasEstimate() && mUserCurrencyBuy > 0);
+	std::string estimated = (mUserCurrencyBuy == 0) ? mPanel.getString("estimated_zero") : getLocalEstimate();
+	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", estimated);
+	mPanel.getChildView("currency_est")->setVisible( hasEstimate() || mUserCurrencyBuy == 0);
 
 	mPanel.getChildView("currency_links")->setVisible( mSupportsInternationalBilling);
 	mPanel.getChildView("exchange_rate_note")->setVisible( mSupportsInternationalBilling);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 25348474a1..b039475389 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -32,6 +32,8 @@
 #include "llcurrencyuimanager.h"
 #include "llfloater.h"
 #include "llfloaterreg.h"
+#include "lllayoutstack.h"
+#include "lliconctrl.h"
 #include "llnotificationsutil.h"
 #include "llstatusbar.h"
 #include "lltextbox.h"
@@ -60,6 +62,7 @@ public:
 	bool		mHasTarget;
 	std::string	mTargetName;
 	S32			mTargetPrice;
+	S32			mRequiredAmount;
 	
 public:
 	void noTarget();
@@ -68,6 +71,7 @@ public:
 	virtual BOOL postBuild();
 	
 	void updateUI();
+	void collapsePanels(bool collapse);
 
 	virtual void draw();
 	virtual BOOL canClose();
@@ -92,7 +96,9 @@ LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
 LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key)
 :	LLFloater(key),
 	mChildren(*this),
-	mManager(*this)
+	mManager(*this),
+	mHasTarget(false),
+	mTargetPrice(0)
 {
 }
 
@@ -104,7 +110,8 @@ LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI()
 void LLFloaterBuyCurrencyUI::noTarget()
 {
 	mHasTarget = false;
-	mManager.setAmount(STANDARD_BUY_AMOUNT);
+	mTargetPrice = 0;
+	mManager.setAmount(0);
 }
 
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
@@ -120,7 +127,8 @@ void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 		need = 0;
 	}
 	
-	mManager.setAmount(need + MINIMUM_BALANCE_AMOUNT);
+	mRequiredAmount = need + MINIMUM_BALANCE_AMOUNT;
+	mManager.setAmount(0);
 }
 
 
@@ -175,7 +183,6 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
 	getChildView("contacting")->setVisible(FALSE);
-	getChildView("buy_action")->setVisible(FALSE);
 
 	if (hasError)
 	{
@@ -208,8 +215,8 @@ void LLFloaterBuyCurrencyUI::updateUI()
 		{
 			if (mHasTarget)
 			{
-				getChildView("buy_action")->setVisible( true);
-				getChild<LLUICtrl>("buy_action")->setTextArg("[ACTION]", mTargetName);
+				getChild<LLUICtrl>("target_price")->setTextArg("[AMT]", llformat("%d", mTargetPrice));
+				getChild<LLUICtrl>("required_amount")->setTextArg("[AMT]", llformat("%d", mRequiredAmount));
 			}
 		}
 		
@@ -230,18 +237,40 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 		if (mHasTarget)
 		{
-			if (total >= mTargetPrice)
-			{
-				getChildView("purchase_warning_repurchase")->setVisible( true);
-			}
-			else
-			{
-				getChildView("purchase_warning_notenough")->setVisible( true);
-			}
+			getChildView("purchase_warning_repurchase")->setVisible( !getChildView("currency_links")->getVisible());
 		}
 	}
 
-	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError);
+	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError && !getChildView("currency_est")->getVisible());
+}
+
+void LLFloaterBuyCurrencyUI::collapsePanels(bool collapse)
+{
+	LLLayoutPanel* price_panel = getChild<LLLayoutPanel>("layout_panel_price");
+	
+	if (price_panel->isCollapsed() == collapse)
+		return;
+	
+	LLLayoutStack* outer_stack = getChild<LLLayoutStack>("outer_stack");	
+	LLLayoutPanel* required_panel = getChild<LLLayoutPanel>("layout_panel_required");
+	LLLayoutPanel* msg_panel = getChild<LLLayoutPanel>("layout_panel_msg");
+
+	S32 delta_height = price_panel->getRect().getHeight() + required_panel->getRect().getHeight() + msg_panel->getRect().getHeight();
+	delta_height *= (collapse ? -1 : 1);
+
+	LLIconCtrl* icon = getChild<LLIconCtrl>("normal_background");
+	LLRect rect = icon->getRect();
+	icon->setRect(rect.setOriginAndSize(rect.mLeft, rect.mBottom - delta_height, rect.getWidth(), rect.getHeight() + delta_height));
+
+	outer_stack->collapsePanel(price_panel, collapse);
+	outer_stack->collapsePanel(required_panel, collapse);
+	outer_stack->collapsePanel(msg_panel, collapse);
+
+	outer_stack->updateLayout();
+
+	LLRect floater_rect = getRect();
+	floater_rect.mBottom -= delta_height;
+	setShape(floater_rect, false);
 }
 
 void LLFloaterBuyCurrencyUI::onClickBuy()
@@ -265,6 +294,7 @@ void LLFloaterBuyCurrency::buyCurrency()
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->noTarget();
 	ui->updateUI();
+	ui->collapsePanels(true);
 }
 
 // static
@@ -273,6 +303,7 @@ void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->target(name, price);
 	ui->updateUI();
+	ui->collapsePanels(false);
 }
 
 
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 061af1b67c..e8e83301be 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <floater
- legacy_header_height="18"
+
  can_minimize="false"
- height="275"
+ height="285"
  layout="topleft"
  title="BUY L$"
  name="buy currency"
@@ -17,277 +17,385 @@
      name="info_cannot_buy">
         Unable to Buy
     </floater.string>
+    <floater.string
+     name="estimated_zero">
+        US$ 0.00
+    </floater.string>
     <icon
-     height="215"
+     height="245"
      image_name="Linden_Dollar_Background"
      layout="topleft"
      left="0"
      name="normal_background"
-     top="17"
+     top="0"
      use_draw_context_alpha="false"
      width="350" />
-   <text
-     type="string"
-     length="1"
-     follows="top|left|right"
-     font="SansSerifHuge"
-     layout="topleft"
-     left="20"
-     height="30"
-     top="25"
-     width="340"
-     name="info_need_more">
-        You need more L$
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     height="16"
+  <layout_stack
+    animate="false"
+    name="outer_stack"
+    layout="topleft"
+    follows="all"
+    orientation="vertical"
+    left="0"
+    top="0"
+    width="350"
+    height="285">
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_title"
      layout="topleft"
-     top="246"
-     left="15"
-     width="300"
-     name="contacting">
-        Contacting LindeX...
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifHuge"
+     follows="all"
+     width="350"
+     height="35">
+      <text
+       type="string"
+       length="1"
+       follows="top|left|right"
+       font="SansSerifLarge"
+       layout="topleft"
+       left="20"
+       height="30"
+       top="8"
+       width="340"
+       name="info_need_more">
+          You need more L$
+      </text>
+      <text
+       type="string"
+       length="1"
+       follows="top|left|right"
+       font="SansSerifLarge"
+       layout="topleft"
+       left="20"
+       height="30"
+       top="8"
+       width="300"
+       name="info_buying">
+          Buy L$
+      </text>
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border"
+       top_delta="25"
+       width="300"/>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_price"
      layout="topleft"
-     left="20"
-     height="30"
-     top="25"
-     width="300"
-     name="info_buying">
-        Buy L$
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifMedium"
-     height="16"
+     follows="all"
+     width="350"
+     height="18">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="target_price_label"
+       top_pad="3"
+       width="210">
+          You need
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="target_price"
+       top_delta="0"
+       width="120">
+          L$ [AMT]
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_balance"
      layout="topleft"
-     left="20"
-     name="balance_label"
-     top="65"
-     width="210">
-        I have
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     follows="top|left"
-     halign="right"
-     height="16"
-     layout="topleft"
-     left="200"
-     name="balance_amount"
-     top_delta="0"
-     width="120">
+     follows="all"
+     width="350"
+     height="19">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="balance_label"
+       top_pad="5"
+       width="210">
+        You now have
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="balance_amount"
+       top_delta="0"
+       width="120">
         L$ [AMT]
-    </text>
-    <text
-     type="string"
-     length="1"
-     follows="top|left"
-     font="SansSerifMedium"
-     height="16"
-     top="95"
-     layout="topleft"
-     left="20"
-     name="currency_action"
-     width="210">
-        I want to buy
-    </text>
-    <text
-     font="SansSerifMedium"
-     type="string"
-     length="1"
-     follows="left|top"
-     height="16"
-     layout="topleft"
-     top_delta="0"
-     left="217"
-     name="currency_label"
-     width="15">
-      L$
-    </text>
-    <line_editor
-     type="string"
-     max_length_bytes="10"
-     halign="right"
-     font="SansSerifMedium"
-     select_on_focus="true"
-     follows="top|left"
-     top_delta="-7"
-     height="22"
-     label="L$"
-     left_pad="3"
-     name="currency_amt"
-     width="85">
-        1234
-    </line_editor>
-    <text
-     type="string"
-     font="SansSerifMedium"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     left="20"
-     top="125"
-     name="buying_label"
-     width="210">
-        For the price
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     text_color="EmphasisColor"
-     follows="top|left"
-     halign="right"
-     height="16"
-     top_delta="0"
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_required"
      layout="topleft"
-     left="150"
-     name="currency_est"
-     width="170">
-     approx. [LOCALAMOUNT]
-    </text>
-    <text
-     type="string"
-     font="SansSerifSmall"
-     text_color="EmphasisColor"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     top="125"
-     left="170"
-     width="150"
-     halign="right"
-     name="getting_data">
-        Estimating...
-    </text>
-    <text
-     type="string"
-     font="SansSerifSmall"
-     top="145"
-     length="1"
-     follows="top|left"
-     height="16"
-     halign="right"
-     left="20"
-     width="300"
-     layout="topleft"
-     name="buy_action">
-        [ACTION]
-    </text>
-    <text
-     type="string"
-     font="SansSerifMedium"
-     length="1"
-     follows="top|left"
-     height="16"
-     layout="topleft"
-     left="20"
-     name="total_label"
-     top="165"
-     width="210">
-        My new balance will be
-    </text>
-    <text
-     type="string"
-     length="1"
-     font="SansSerifMedium"
-     follows="top|left"
-     top_delta="0"
-     height="16"
-     layout="topleft"
-     left="200"
-     halign="right"
-     name="total_amount"
-     width="120">
+     follows="all"
+     width="350"
+     height="22">
+      <text
+        type="string"
+        length="1"
+        follows="top|left"
+        font="SansSerifMedium"
+        font.style="BOLD"
+        height="16"
+        layout="topleft"
+        left="20"
+        name="required_label"
+        top_pad="6"
+        width="210">
+        You should buy at least
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       halign="right"
+       height="16"
+       layout="topleft"
+       left="200"
+       name="required_amount"
+       top_delta="0"
+       width="120">
         L$ [AMT]
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_action"
      layout="topleft"
-     halign="right"
-     top="189"
-     left="20"
-     width="300"
-     height="30"
-     name="currency_links">
-      [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
+     follows="all"
+     width="350"
+     height="90">
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border_2"
+       top_pad="5"
+       width="300"/>
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       font="SansSerifMedium"
+       height="16"
+       top_pad="15"
+       layout="topleft"
+       left="20"
+       name="currency_action"
+       width="210">
+          Choose amount to buy
+      </text>
+      <text
+       font="SansSerifMedium"
+       type="string"
+       length="1"
+       follows="left|top"
+       height="16"
+       layout="topleft"
+       top_delta="0"
+       left="247"
+       name="currency_label"
+       width="15">
+        L$
+      </text>
+      <line_editor
+       type="string"
+       max_length_bytes="10"
+       halign="right"
+       font="SansSerifMedium"
+       select_on_focus="true"
+       follows="top|left"
+       top_delta="-4"
+       height="22"
+       label="L$"
+       left_pad="3"
+       name="currency_amt"
+       width="55">
+          1234
+      </line_editor>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       text_color="EmphasisColor"
+       follows="top|left"
+       halign="right"
+       height="16"
+       top_pad="4"
+       layout="topleft"
+       left="150"
+       name="currency_est"
+       width="170">
+       Approx. [LOCALAMOUNT]
+      </text>
+      <text
+       type="string"
+       font="SansSerifSmall"
+       text_color="EmphasisColor"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       left="170"
+       top_delta="0"
+       width="150"
+       halign="right"
+       name="getting_data">
+          Estimating...
+      </text>
+      <text
+       type="string"
+       font="SansSerifMedium"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       left="20"
+       name="total_label"
+       top_pad="10"
+       width="210">
+          Your new balance will be
+      </text>
+      <text
+       type="string"
+       length="1"
+       font="SansSerifMedium"
+       follows="top|left"
+       top_delta="0"
+       height="16"
+       layout="topleft"
+       left="200"
+       halign="right"
+       name="total_amount"
+       width="120">
+          L$ [AMT]
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_msg"
      layout="topleft"
-     halign="right"
-     top="202"
-     left="20"
-     width="300"
-     height="30"
-     name="exchange_rate_note">
+     follows="all"
+     width="350"
+     height="50">
+      <view_border
+       bevel_style="none"
+       height="0"
+       layout="topleft"
+       left="20"
+       name="text_border_3"
+       top_pad="0"
+       width="300"/>
+      <text
+       type="string"
+       length="1"
+       text_color="LtGray_50"
+       follows="top|left"
+       layout="topleft"
+       halign="right"
+       top_pad="3"
+       left="20"
+       width="300"
+       height="30"
+       name="currency_links">
+        [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
+      </text>
+      <text
+       type="string"
+       length="1"
+       text_color="LtGray_50"
+       follows="top|left"
+       layout="topleft"
+       halign="right"
+       top="19"
+       left="20"
+       width="300"
+       height="30"
+       name="exchange_rate_note">
 Re-enter amount to see the latest exchange rate.
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
-     layout="topleft"
-     halign="right"
-     top="208"
-     left="10"
-     width="310"
-     height="35"
-     name="purchase_warning_repurchase">
-        Confirming this purchase only buys L$, not the object.
-    </text>
-    <text
-     type="string"
-     length="1"
-     text_color="LtGray_50"
-     follows="top|left"
-     layout="topleft"
-     halign="right"
-     top="213"
-     left="20"
-     width="300"
-     height="30"
-     name="purchase_warning_notenough">
-        You aren&apos;t buying enough L$. Please increase the amount.
-    </text>
-
-    <button
-     follows="bottom|left"
-     height="20"
-     label="Buy Now"
-     layout="topleft"
-     left="151"
-     name="buy_btn"
-     top="242"
-     width="90"/>
-    <button
-     follows="bottom|right"
-     height="20"
-     label="Cancel"
+      </text>
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       layout="topleft"
+       font="SansSerifMedium"
+       top="10"
+       left="20"
+       width="310"
+       height="35"
+       name="purchase_warning_repurchase">
+After you receive your L$, you should try your
+purchase again.
+      </text>
+    </layout_panel>
+    <layout_panel
+     auto_resize="false"
+     name="layout_panel_buttons"
      layout="topleft"
-     left_pad="10"
-     name="cancel_btn"
-     width="90"/>
+     follows="all"
+     width="350"
+     height="40">
+      <text
+       type="string"
+       length="1"
+       follows="top|left"
+       height="16"
+       layout="topleft"
+       top_pad="0"
+       left="15"
+       width="300"
+       name="contacting">
+          Contacting LindeX...
+        </text>
+      <button
+       follows="top|left|right"
+       height="20"
+       label="Buy L$ now"
+       layout="topleft"
+       left="151"
+       name="buy_btn"
+       bottom_delta ="8"
+       width="90"/>
+      <button
+       follows="top|left|right"
+       height="20"
+       label="Cancel"
+       layout="topleft"
+       left_pad="10"     
+       name="cancel_btn"
+       width="90"/>
+    </layout_panel>
+  </layout_stack>
 </floater>
-- 
cgit v1.2.3


From 85d90ce6bda00f1cb6fc8f0a75e739f1273843b3 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 3 Sep 2020 19:39:57 +0300
Subject: SL-13814 mac build fix

---
 indra/newview/llfloaterbuycurrency.cpp | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b039475389..b183ba6912 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -44,7 +44,6 @@
 #include "llwindow.h"
 #include "llappviewer.h"
 
-static const S32 STANDARD_BUY_AMOUNT = 2000;
 static const S32 MINIMUM_BALANCE_AMOUNT = 0;
 
 class LLFloaterBuyCurrencyUI
-- 
cgit v1.2.3


From 1557cd8fe2733c32c7788daf752fe23c7190947f Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 4 Sep 2020 19:55:26 +0300
Subject: SL-13814 Updated label text

---
 indra/newview/llfloaterbuycurrency.cpp         |  7 +++++--
 indra/newview/llviewermenu.cpp                 |  2 +-
 indra/newview/llviewermenufile.cpp             | 10 ++--------
 indra/newview/skins/default/xui/en/strings.xml |  8 ++++----
 4 files changed, 12 insertions(+), 15 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b183ba6912..dfc755c370 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -59,7 +59,6 @@ public:
 	LLCurrencyUIManager	mManager;
 	
 	bool		mHasTarget;
-	std::string	mTargetName;
 	S32			mTargetPrice;
 	S32			mRequiredAmount;
 	
@@ -116,9 +115,13 @@ void LLFloaterBuyCurrencyUI::noTarget()
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 {
 	mHasTarget = true;
-	mTargetName = name;
 	mTargetPrice = price;
 	
+	if (!name.empty())
+	{
+		getChild<LLUICtrl>("target_price_label")->setValue(name);
+	}
+
 	S32 balance = gStatusBar->getBalance();
 	S32 need = price - balance;
 	if (need < 0)
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b333b94462..546d8e5377 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4897,7 +4897,7 @@ void handle_buy_or_take()
 		{
 			LLStringUtil::format_map_t args;
 			args["AMOUNT"] = llformat("%d", total_price);
-			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price );
+			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price );
 		}
 	}
 	else
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index cd48b1e8e7..7d52607cba 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -825,10 +825,7 @@ void upload_done_callback(
 				
 				if(!(can_afford_transaction(expected_upload_cost)))
 				{
-					LLStringUtil::format_map_t args;
-					args["NAME"] = data->mAssetInfo.getName();
-					args["AMOUNT"] = llformat("%d", expected_upload_cost);
-					LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost );
+					LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost );
 					is_balance_sufficient = FALSE;
 				}
 				else if(region)
@@ -962,10 +959,7 @@ void upload_new_resource(
 			if (balance < uploadInfo->getExpectedUploadCost())
 			{
 				// insufficient funds, bail on this upload
-				LLStringUtil::format_map_t args;
-				args["NAME"] = uploadInfo->getName();
-                args["AMOUNT"] = llformat("%d", uploadInfo->getExpectedUploadCost());
-                LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), uploadInfo->getExpectedUploadCost());
+                LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost());
 				return;
 			}
 		}
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c9ea423a20..3f06d658d7 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2833,7 +2833,6 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="AcquiredItems">Acquired Items</string>
 	<string name="Cancel">Cancel</string>
 	<string name="UploadingCosts">Uploading [NAME] costs L$ [AMOUNT]</string>
-	<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
 	<string name="UnknownFileExtension">
 		Unknown file extension .%s
 Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
@@ -3789,11 +3788,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="to upload">to upload</string>
   <string name="to publish a classified ad">to publish a classified ad</string>
 
-  <string name="giving">Giving L$ [AMOUNT]</string>
   <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
   <string name="this_costs">This costs L$ [AMOUNT]</string>
-  <string name="buying_selected_land">Buying selected land for L$ [AMOUNT]</string>
-  <string name="this_object_costs">This object costs L$ [AMOUNT]</string>
+  
+  <string name="buying_selected_land">This land costs</string>
+  <string name="this_object_costs">This item costs</string>
+  <string name="giving">You want to give</string>
 
   <string name="group_role_everyone">Everyone</string>
   <string name="group_role_officers">Officers</string>
-- 
cgit v1.2.3


From f9ed4fedab7c7deab20aeddd88ab40f3958af5a3 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 7 Sep 2020 12:14:27 +0300
Subject: SL-13878 FIXED The no title location appears in 'Teleport history'
 after adding a blank line to teleport_history.txt

---
 indra/newview/llteleporthistorystorage.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index 8a5704939a..658ab453d2 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -201,6 +201,12 @@ void LLTeleportHistoryStorage::load()
 	std::string line;
 	while (std::getline(file, line))
 	{
+		if (line.empty())
+		{
+			LL_WARNS() << "Teleport history contains empty line."<< LL_ENDL;
+			continue;
+		}
+		
 		LLSD s_item;
 		std::istringstream iss(line);
 		if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
-- 
cgit v1.2.3


From 6f16e6c4e0836353cb1a8d2c356abe4de78d315a Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 7 Sep 2020 23:23:17 +0300
Subject: SL-3278 Wrap debug code into debug option

---
 indra/newview/llvoavatar.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index d567623ac0..c5ae80dca3 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -10432,8 +10432,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
 
 		// Diagnostic output to identify all avatar-related textures.
 		// Does not affect rendering cost calculation.
-		// Could be wrapped in a debug option if output becomes problematic.
-		if (isSelf())
+		if (isSelf() && debugLoggingEnabled("ARCdetail"))
 		{
 			// print any attachment textures we didn't already know about.
 			for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
-- 
cgit v1.2.3


From 76ee89fb50e394bdaa1cfc85d57d76666beca7fb Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 8 Sep 2020 21:30:54 +0300
Subject: SL-3278 Parts unique to 'self' should not affect render complexity

---
 indra/newview/llvoavatar.cpp | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index c5ae80dca3..8cc0cc174c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -10388,10 +10388,23 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
 			ETextureIndex tex_index = baked_dict->mTextureIndex;
 			if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
 			{
-				if (isTextureVisible(tex_index))
-				{
-					cost +=COMPLEXITY_BODY_PART_COST;
-				}
+                // Same as isTextureVisible(), but doesn't account for isSelf to ensure identical numbers for all avatars
+                if (isIndexLocalTexture(tex_index))
+                {
+                    if (isTextureDefined(tex_index, 0))
+                    {
+                        cost += COMPLEXITY_BODY_PART_COST;
+                    }
+                }
+                else
+                {
+                    // baked textures can use TE images directly
+                    if (isTextureDefined(tex_index)
+                        && (getTEImage(tex_index)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha))
+                    {
+                        cost += COMPLEXITY_BODY_PART_COST;
+                    }
+                }
 			}
 		}
         LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL;
-- 
cgit v1.2.3


From dceab3c78bb49eab28d1307bb7544e4b2b7763f0 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 8 Sep 2020 21:41:53 +0300
Subject: SL-3278 Compensate for randomly-switching textures

---
 indra/newview/llvovolume.cpp | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 98eb2d3cdc..4799fb467f 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3972,7 +3972,25 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
 		{
 			if (textures.find(img->getID()) == textures.end())
 			{
-				S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
+                S32 texture_cost = 0;
+                S8 type = img->getType();
+                if (type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
+                {
+                    const LLViewerFetchedTexture* fetched_texturep = dynamic_cast<const LLViewerFetchedTexture*>(img);
+                    if (fetched_texturep
+                        && fetched_texturep->getFTType() == FTT_LOCAL_FILE
+                        && (img->getID() == IMG_ALPHA_GRAD_2D || img->getID() == IMG_ALPHA_GRAD)
+                        )
+                    {
+                        // These two textures appear to switch between each other, but are of different sizes (4x256 and 256x256).
+                        // Hardcode cost from larger one to not cause random complexity changes
+                        texture_cost = 320;
+                    }
+                }
+                if (texture_cost == 0)
+                {
+                    texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f));
+                }
 				textures.insert(texture_cost_t::value_type(img->getID(), texture_cost));
 			}
 		}
-- 
cgit v1.2.3


From 45758daa8a1f388f5881f5025063e13b10ff7721 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 9 Sep 2020 15:21:27 +0300
Subject: SL-3278 Small adjustement

---
 indra/newview/llvoavatar.cpp | 3 ++-
 indra/newview/llvovolume.cpp | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 8cc0cc174c..2587967d15 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -10288,7 +10288,8 @@ void LLVOAvatar::accountRenderComplexityForObject(
                             LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()
                                                    << " total: " << attachment_total_cost
                                                    << ", volume: " << attachment_volume_cost
-                                                   << ", textures: " << attachment_texture_cost
+                                                   << ", " << textures.size()
+                                                   << " textures: " << attachment_texture_cost
                                                    << ", " << volume->numChildren()
                                                    << " children: " << attachment_children_cost
                                                    << LL_ENDL;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 4799fb467f..e23b54f60c 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3976,7 +3976,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const
                 S8 type = img->getType();
                 if (type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE)
                 {
-                    const LLViewerFetchedTexture* fetched_texturep = dynamic_cast<const LLViewerFetchedTexture*>(img);
+                    const LLViewerFetchedTexture* fetched_texturep = static_cast<const LLViewerFetchedTexture*>(img);
                     if (fetched_texturep
                         && fetched_texturep->getFTType() == FTT_LOCAL_FILE
                         && (img->getID() == IMG_ALPHA_GRAD_2D || img->getID() == IMG_ALPHA_GRAD)
-- 
cgit v1.2.3


From 8c8eac256bdb51fdf9e6e297280b2017d26c3588 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 11 Sep 2020 16:31:15 +0300
Subject: SL-13927 Turn SSL verification On for all SL services in viewer

---
 indra/llcorehttp/httpoptions.cpp      | 11 ++++++++++-
 indra/llcorehttp/httpoptions.h        | 11 ++++++++++-
 indra/llcrashlogger/llcrashlogger.cpp |  1 +
 indra/newview/llappcorehttp.cpp       | 24 ++++++++++++++++++++++++
 indra/newview/llappcorehttp.h         |  1 +
 indra/newview/llfloaterabout.cpp      |  1 +
 indra/newview/llfloatergridstatus.cpp |  1 +
 indra/newview/lltranslate.cpp         |  2 ++
 8 files changed, 50 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index df5aa52fa9..c6365e5091 100644
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -32,6 +32,7 @@
 namespace LLCore
 {
 
+    bool HttpOptions::sDefaultVerifyPeer = false;
 
 HttpOptions::HttpOptions() :
     mWantHeaders(false),
@@ -43,7 +44,7 @@ HttpOptions::HttpOptions() :
     mMaxRetryBackoff(HTTP_RETRY_BACKOFF_MAX_DEFAULT),
     mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),
     mFollowRedirects(true),
-    mVerifyPeer(false),
+    mVerifyPeer(sDefaultVerifyPeer),
     mVerifyHost(false),
     mDNSCacheTimeout(-1L),
     mNoBody(false)
@@ -122,7 +123,15 @@ void HttpOptions::setHeadersOnly(bool nobody)
 {
     mNoBody = nobody;
     if (mNoBody)
+    {
         setWantHeaders(true);
+        setSSLVerifyPeer(false);
+    }
+}
+
+void HttpOptions::setDefaultSSLVerifyPeer(bool verify)
+{
+    sDefaultVerifyPeer = verify;
 }
 
 }   // end namespace LLCore
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 8a6de61b04..41f71896b0 100644
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -143,7 +143,7 @@ public:
 
     /// Instructs the LLCore::HTTPRequest to verify that the exchanged security
     /// certificate is authentic. 
-    /// Default: false
+    /// Default: sDefaultVerifyPeer
     void				setSSLVerifyPeer(bool verify);
 	bool				getSSLVerifyPeer() const
 	{
@@ -177,6 +177,13 @@ public:
     {
         return mNoBody;
     }
+
+    /// Sets default behavior for verifying that the name in the 
+    /// security certificate matches the name of the host contacted.
+    /// Defaults false if not set, but should be set according to
+    /// viewer's initialization options and command argunments, see
+    /// NoVerifySSLCert
+    static void         setDefaultSSLVerifyPeer(bool verify);
 	
 protected:
 	bool				mWantHeaders;
@@ -192,6 +199,8 @@ protected:
 	bool        		mVerifyHost;
 	int					mDNSCacheTimeout;
     bool                mNoBody;
+
+    static bool         sDefaultVerifyPeer;
 }; // end class HttpOptions
 
 
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 62fcdaf545..e02f3a6306 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -411,6 +411,7 @@ bool LLCrashLogger::runCrashLogPost(std::string host, LLSD data, std::string msg
     LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
 
     httpOpts->setTimeout(timeout);
+    httpOpts->setSSLVerifyPeer(false);
 
 	for(int i = 0; i < retries; ++i)
 	{
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index afa4414968..4777662839 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -116,6 +116,7 @@ static const struct
 };
 
 static void setting_changed();
+static void ssl_verification_changed();
 
 
 LLAppCoreHttp::HttpClass::HttpClass()
@@ -195,6 +196,23 @@ void LLAppCoreHttp::init()
 		LL_WARNS("Init") << "Failed to set SSL Verification.  Reason:  " << status.toString() << LL_ENDL;
 	}
 
+    // Set up Default SSL Verification option.
+    const std::string no_verify_ssl("NoVerifySSLCert");
+    if (gSavedSettings.controlExists(no_verify_ssl))
+    {
+        LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(no_verify_ssl);
+        if (cntrl_ptr.isNull())
+        {
+            LL_WARNS("Init") << "Unable to set signal on global setting '" << no_verify_ssl
+                << "'" << LL_ENDL;
+        }
+        else
+        {
+            mSSLNoVerifySignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&ssl_verification_changed));
+            LLCore::HttpOptions::setDefaultSSLVerifyPeer(!cntrl_ptr->getValue().asBoolean());
+        }
+    }
+
 	// Tracing levels for library & libcurl (note that 2 & 3 are beyond spammy):
 	// 0 - None
 	// 1 - Basic start, stop simple transitions
@@ -296,6 +314,11 @@ void setting_changed()
 	LLAppViewer::instance()->getAppCoreHttp().refreshSettings(false);
 }
 
+void ssl_verification_changed()
+{
+    LLCore::HttpOptions::setDefaultSSLVerifyPeer(!gSavedSettings.getBOOL("NoVerifySSLCert"));
+}
+
 namespace
 {
     // The NoOpDeletor is used when wrapping LLAppCoreHttp in a smart pointer below for
@@ -355,6 +378,7 @@ void LLAppCoreHttp::cleanup()
 	{
 		mHttpClasses[i].mSettingsSignal.disconnect();
 	}
+    mSSLNoVerifySignal.disconnect();
 	mPipelinedSignal.disconnect();
 	
 	delete mRequest;
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index 95c138d598..751c498ab0 100644
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -256,6 +256,7 @@ private:
 	HttpClass					mHttpClasses[AP_COUNT];
 	bool						mPipelined;				// Global setting
 	boost::signals2::connection	mPipelinedSignal;		// Signal for 'HttpPipelining' setting
+	boost::signals2::connection	mSSLNoVerifySignal;		// Signal for 'NoVerifySSLCert' setting
 
 	static LLCore::HttpStatus	sslVerify(const std::string &uri, const LLCore::HttpHandler::ptr_t &handler, void *appdata);
 };
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 171858e472..1fbd198019 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -236,6 +236,7 @@ void LLFloaterAbout::fetchServerReleaseNotesCoro(const std::string& cap_url)
 
     httpOpts->setWantHeaders(true);
     httpOpts->setFollowRedirects(false);
+    httpOpts->setSSLVerifyPeer(false); // We want this data even if SSL verification fails
 
     LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts);
 
diff --git a/indra/newview/llfloatergridstatus.cpp b/indra/newview/llfloatergridstatus.cpp
index faa7e9f3db..9745e17bbb 100644
--- a/indra/newview/llfloatergridstatus.cpp
+++ b/indra/newview/llfloatergridstatus.cpp
@@ -95,6 +95,7 @@ void LLFloaterGridStatus::getGridStatusRSSCoro()
     LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
     LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
 
+    httpOpts->setSSLVerifyPeer(false); // We want this data even if SSL fails
     httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
     std::string url = gSavedSettings.getString("GridStatusRSS");
 
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index fa3b44f702..553a3cd086 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -144,6 +144,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::
     httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
 
     httpOpts->setFollowRedirects(true);
+    httpOpts->setSSLVerifyPeer(false);
 
     std::string url = this->getKeyVerificationURL(key);
     if (url.empty())
@@ -185,6 +186,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
 
     httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN);
     httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
+    httpOpts->setSSLVerifyPeer(false);
 
     std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg);
     if (url.empty())
-- 
cgit v1.2.3


From 5cceddbc359814f522e211467048ffa6d7d99c0d Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 14 Sep 2020 12:13:33 +0300
Subject: SL-13930 Appearance sort order should be similar to Inventory sort
 order

---
 indra/newview/lloutfitgallery.cpp | 4 +---
 indra/newview/lloutfitslist.cpp   | 5 +----
 2 files changed, 2 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 852ba846ff..3d1428bb63 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -166,9 +166,7 @@ bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
         std::string name1 = item1->getItemName();
         std::string name2 = item2->getItemName();
 
-        LLStringUtil::toUpper(name1);
-        LLStringUtil::toUpper(name2);
-        return name1 < name2;
+        return (LLStringUtil::compareDict(name1, name2) < 0);
     }
     else
     {
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 71ab826e1c..423e57978a 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -59,10 +59,7 @@ bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LL
 	std::string name1 = tab1->getTitle();
 	std::string name2 = tab2->getTitle();
 
-	LLStringUtil::toUpper(name1);
-	LLStringUtil::toUpper(name2);
-
-	return name1 < name2;
+    return (LLStringUtil::compareDict(name1, name2) < 0);
 }
 
 struct outfit_accordion_tab_params : public LLInitParam::Block<outfit_accordion_tab_params, LLAccordionCtrlTab::Params>
-- 
cgit v1.2.3


From a258e633f2e158e6981ab7d3e01a7a3b46242c10 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 14 Sep 2020 15:18:52 +0300
Subject: SL-13937 FIXED 'Loading...' is constantly displayed when entering the
 URL on the 'Media URL' floater

---
 indra/newview/llfloaterurlentry.cpp                      | 9 +++++++--
 indra/newview/llfloaterurlentry.h                        | 1 +
 indra/newview/skins/default/xui/en/floater_url_entry.xml | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index f2efef0c33..63bce3d2eb 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -122,8 +122,7 @@ void LLFloaterURLEntry::headerFetchComplete(S32 status, const std::string& mime_
 		}
 
 	}
-	// Decrement the cursor
-	getWindow()->decBusyCount();
+
 	getChildView("loading_label")->setVisible( false);
 	closeFloater();
 }
@@ -302,3 +301,9 @@ bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const
 	}
 	return false;
 }
+
+void LLFloaterURLEntry::onClose( bool app_quitting )
+{
+    // Decrement the cursor
+    getWindow()->decBusyCount();
+}
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index 20f4604907..04a8eca069 100644
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -42,6 +42,7 @@ public:
 	// that panel via the handle.
 	static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle, const std::string media_url);
 	/*virtual*/	BOOL	postBuild();
+    /*virtual*/ void onClose( bool app_quitting );
 	void headerFetchComplete(S32 status, const std::string& mime_type);
 
 	bool addURLToCombobox(const std::string& media_url);
diff --git a/indra/newview/skins/default/xui/en/floater_url_entry.xml b/indra/newview/skins/default/xui/en/floater_url_entry.xml
index 29fb29fabf..2dfc0fd125 100644
--- a/indra/newview/skins/default/xui/en/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml
@@ -66,7 +66,7 @@
      layout="topleft"
      left="152"
      name="loading_label"
-     visible="true">
+     visible="false">
         Loading...
     </text>
 </floater>
-- 
cgit v1.2.3


From b193defea81f279f366035d628941e4f463b25fe Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 15 Sep 2020 21:18:16 +0300
Subject: SL-13923 - EEP sky is wrong after loading water then re-logging with
 EnvironmentPersistAcrossLogin

---
 indra/newview/llenvironment.cpp | 68 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 64 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 342ee3ccf5..72047e9407 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1130,8 +1130,38 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm
     }
     else if (!environment->getSky())
     {
-        environment->setSky(mCurrentEnvironment->getSky());
-        environment->setFlags(DayInstance::NO_ANIMATE_SKY);
+        if (mCurrentEnvironment->getEnvironmentSelection() != ENV_NONE)
+        {
+            // Note: This looks suspicious. Shouldn't we assign whole day if mCurrentEnvironment has whole day?
+            // and then add water/sky on top
+            // This looks like it will result in sky using single keyframe instead of whole day if day is present
+            // when setting static water without static sky
+            environment->setSky(mCurrentEnvironment->getSky());
+            environment->setFlags(DayInstance::NO_ANIMATE_SKY);
+        }
+        else
+        {
+            // Environment is not properly initialized yet, but we should have environment by this point
+            DayInstance::ptr_t substitute = getEnvironmentInstance(ENV_PARCEL, true);
+            if (!substitute || !substitute->getSky())
+            {
+                substitute = getEnvironmentInstance(ENV_REGION, true);
+            }
+            if (!substitute || !substitute->getSky())
+            {
+                substitute = getEnvironmentInstance(ENV_DEFAULT, true);
+            }
+
+            if (substitute && substitute->getSky())
+            {
+                environment->setSky(substitute->getSky());
+                environment->setFlags(DayInstance::NO_ANIMATE_SKY);
+            }
+            else
+            {
+                LL_WARNS("ENVIRONMENT") << "Failed to assign substitute water/sky, environment is not properly initialized" << LL_ENDL;
+            }
+        }
     }
         
     if (fixed.second)
@@ -1141,8 +1171,38 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm
     }
     else if (!environment->getWater())
     {
-        environment->setWater(mCurrentEnvironment->getWater());
-        environment->setFlags(DayInstance::NO_ANIMATE_WATER);
+        if (mCurrentEnvironment->getEnvironmentSelection() != ENV_NONE)
+        {
+            // Note: This looks suspicious. Shouldn't we assign whole day if mCurrentEnvironment has whole day?
+            // and then add water/sky on top
+            // This looks like it will result in water using single keyframe instead of whole day if day is present
+            // when setting static sky without static water
+            environment->setWater(mCurrentEnvironment->getWater());
+            environment->setFlags(DayInstance::NO_ANIMATE_WATER);
+        }
+        else
+        {
+            // Environment is not properly initialized yet, but we should have environment by this point
+            DayInstance::ptr_t substitute = getEnvironmentInstance(ENV_PARCEL, true);
+            if (!substitute || !substitute->getWater())
+            {
+                substitute = getEnvironmentInstance(ENV_REGION, true);
+            }
+            if (!substitute || !substitute->getWater())
+            {
+                substitute = getEnvironmentInstance(ENV_DEFAULT, true);
+            }
+
+            if (substitute && substitute->getWater())
+            {
+                environment->setWater(substitute->getWater());
+                environment->setFlags(DayInstance::NO_ANIMATE_WATER);
+            }
+            else
+            {
+                LL_WARNS("ENVIRONMENT") << "Failed to assign substitute water/sky, environment is not properly initialized" << LL_ENDL;
+            }
+        }
     }
 
     if (!mSignalEnvChanged.empty())
-- 
cgit v1.2.3


From 177ad21ade8fbbb05ac5c373b8b43176e70e64a7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 17 Sep 2020 19:34:03 +0300
Subject: SL-13729 Performance of LLUI and LLRender2D

---
 indra/llrender/llrender.cpp        |  1 +
 indra/llrender/llrender.h          |  1 +
 indra/llrender/llrender2dutils.cpp | 23 ++++++++++-------------
 indra/llrender/llrender2dutils.h   | 13 +++++--------
 indra/llui/llmultislider.cpp       | 23 +++++++++++------------
 indra/llui/llmultislider.h         |  1 +
 indra/llui/llui.cpp                | 12 ++++++++++++
 indra/llui/llui.h                  | 16 ++++++++--------
 indra/newview/llhudnametag.cpp     | 11 +++++------
 indra/newview/llhudnametag.h       |  4 +++-
 indra/newview/llhudtext.cpp        |  3 ---
 11 files changed, 57 insertions(+), 51 deletions(-)

(limited to 'indra')

diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index ebc4659bcf..9f95b62b8a 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -50,6 +50,7 @@ U32 LLRender::sUIVerts = 0;
 U32 LLTexUnit::sWhiteTexture = 0;
 bool LLRender::sGLCoreProfile = false;
 bool LLRender::sNsightDebugSupport = false;
+LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f);
 
 static const U32 LL_NUM_TEXTURE_LAYERS = 32; 
 static const U32 LL_NUM_LIGHT_UNITS = 8;
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 41f4fe4017..af8568f8a3 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -463,6 +463,7 @@ public:
 	static U32 sUIVerts;
 	static bool sGLCoreProfile;
 	static bool sNsightDebugSupport;
+	static LLVector2 sUIGLScaleFactor;
 
 private:
 	friend class LLLightState;
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 801b945806..dd34f3e383 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -106,11 +106,10 @@ void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixe
 	top += LLFontGL::sCurOrigin.mY;
 
 	gGL.loadUIIdentity();
-	LLRender2D *r2d_inst = LLRender2D::getInstance();
-	gl_rect_2d(llfloor((F32)left * r2d_inst->mGLScaleFactor.mV[VX]) - pixel_offset,
-				llfloor((F32)top * r2d_inst->mGLScaleFactor.mV[VY]) + pixel_offset,
-				llfloor((F32)right * r2d_inst->mGLScaleFactor.mV[VX]) + pixel_offset,
-				llfloor((F32)bottom * r2d_inst->mGLScaleFactor.mV[VY]) - pixel_offset,
+	gl_rect_2d(llfloor((F32)left * LLRender::sUIGLScaleFactor.mV[VX]) - pixel_offset,
+				llfloor((F32)top * LLRender::sUIGLScaleFactor.mV[VY]) + pixel_offset,
+				llfloor((F32)right * LLRender::sUIGLScaleFactor.mV[VX]) + pixel_offset,
+				llfloor((F32)bottom * LLRender::sUIGLScaleFactor.mV[VY]) - pixel_offset,
 				filled);
 	gGL.popUIMatrix();
 }
@@ -1568,7 +1567,6 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv
 
 LLRender2D::LLRender2D(LLImageProviderInterface* image_provider)
 {
-	mGLScaleFactor = LLVector2(1.f, 1.f);
 	mImageProvider = image_provider;
 	if(mImageProvider)
 	{
@@ -1585,7 +1583,7 @@ LLRender2D::~LLRender2D()
 	}
 }
 
-
+// static
 void LLRender2D::translate(F32 x, F32 y, F32 z)
 {
 	gGL.translateUI(x,y,z);
@@ -1594,12 +1592,14 @@ void LLRender2D::translate(F32 x, F32 y, F32 z)
 	LLFontGL::sCurDepth += z;
 }
 
+// static
 void LLRender2D::pushMatrix()
 {
 	gGL.pushUIMatrix();
 	LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
 }
 
+// static
 void LLRender2D::popMatrix()
 {
 	gGL.popUIMatrix();
@@ -1608,6 +1608,7 @@ void LLRender2D::popMatrix()
 	LLFontGL::sOriginStack.pop_back();
 }
 
+// static
 void LLRender2D::loadIdentity()
 {
 	gGL.loadUIIdentity(); 
@@ -1616,15 +1617,11 @@ void LLRender2D::loadIdentity()
 	LLFontGL::sCurDepth = 0.f;
 }
 
-void LLRender2D::setScaleFactor(const LLVector2 &scale_factor)
-{
-	mGLScaleFactor = scale_factor;
-}
-
+// static
 void LLRender2D::setLineWidth(F32 width)
 {
 	gGL.flush();
-	glLineWidth(width * lerp(mGLScaleFactor.mV[VX], mGLScaleFactor.mV[VY], 0.5f));
+	glLineWidth(width * lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f));
 }
 
 LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
index 70ab006fd6..395c153820 100644
--- a/indra/llrender/llrender2dutils.h
+++ b/indra/llrender/llrender2dutils.h
@@ -127,19 +127,16 @@ class LLRender2D : public LLParamSingleton<LLRender2D>
 	LOG_CLASS(LLRender2D);
 	~LLRender2D();
 public:
-	void pushMatrix();
-	void popMatrix();
-	void loadIdentity();
-	void translate(F32 x, F32 y, F32 z = 0.0f);
+	static void pushMatrix();
+	static void popMatrix();
+	static void loadIdentity();
+	static void translate(F32 x, F32 y, F32 z = 0.0f);
 
-	void setLineWidth(F32 width);
-	void setScaleFactor(const LLVector2& scale_factor);
+	static void setLineWidth(F32 width);
 
 	LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
 	LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
 
-	LLVector2		mGLScaleFactor;
-
 protected:
 	// since LLRender2D has no control of image provider's lifecycle
 	// we need a way to tell LLRender2D that provider died and
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index acfe4a0cba..f89064d59a 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -136,6 +136,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 		}
 	}
 
+    mRoundedSquareImgp = LLUI::getUIImage("Rounded_Square");
 	if (p.thumb_image.isProvided())
 	{
 		mThumbImagep = LLUI::getUIImage(p.thumb_image());
@@ -666,8 +667,6 @@ void LLMultiSlider::draw()
 	F32 opacity = getEnabled() ? 1.f : 0.3f;
 
 	// Track
-	LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square");
-
 	static LLUICachedControl<S32> multi_track_height_width ("UIMultiTrackHeight", 0);
 	S32 height_offset = 0;
 	S32 width_offset = 0;
@@ -685,7 +684,7 @@ void LLMultiSlider::draw()
 	if(mDrawTrack)
 	{
 		track_rect.stretch(-1);
-		thumb_imagep->draw(track_rect, mTrackColor.get() % opacity);
+		mRoundedSquareImgp->draw(track_rect, mTrackColor.get() % opacity);
 	}
 
 	// if we're supposed to use a drawn triangle
@@ -704,7 +703,7 @@ void LLMultiSlider::draw()
 				mTriangleColor.get() % opacity, TRUE);
 		}
 	}
-	else if (!thumb_imagep && !mThumbImagep)
+	else if (!mRoundedSquareImgp && !mThumbImagep)
 	{
 		// draw all the thumbs
 		curSldrIt = mThumbRects.end();
@@ -757,7 +756,7 @@ void LLMultiSlider::draw()
 			}
 			else
 			{
-				thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+                mRoundedSquareImgp->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
 			}
 		}
 
@@ -772,7 +771,7 @@ void LLMultiSlider::draw()
 				}
 				else
 				{
-					thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+                    mRoundedSquareImgp->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
 				}
 			}
 		}
@@ -784,7 +783,7 @@ void LLMultiSlider::draw()
             }
             else
             {
-                thumb_imagep->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+                mRoundedSquareImgp->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
             }
         }
 
@@ -822,11 +821,11 @@ void LLMultiSlider::draw()
 			}
 			else if (capture == this)
 			{
-				thumb_imagep->drawSolid(mIt->second, curThumbColor);
+                mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor);
 			}
 			else
 			{
-				thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity);
+                mRoundedSquareImgp->drawSolid(mIt->second, curThumbColor % opacity);
 			}
 		}
 		
@@ -846,11 +845,11 @@ void LLMultiSlider::draw()
 			}
 			else if (capture == this)
 			{
-				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
+                mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
 			}
 			else
 			{
-				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
+                mRoundedSquareImgp->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
 			}
 		}
 		if(hoverSldrIt != mThumbRects.end()) 
@@ -861,7 +860,7 @@ void LLMultiSlider::draw()
 			}
 			else
 			{
-				thumb_imagep->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());
+                mRoundedSquareImgp->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());
 			}
 		}
 	}
diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h
index 99a78d6e09..3cb4b760b0 100644
--- a/indra/llui/llmultislider.h
+++ b/indra/llui/llmultislider.h
@@ -150,6 +150,7 @@ protected:
 	LLUIColor		mDisabledThumbColor;
 	LLUIColor		mTriangleColor;
 	LLUIImagePtr	mThumbImagep; //blimps on the slider, for now no 'disabled' support
+    LLUIImagePtr	mRoundedSquareImgp; //blimps on the slider, for now no 'disabled' support
 
 	const EOrientation	mOrientation;
 
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 656b69d3ed..77b59e5bc5 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -510,6 +510,18 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
 	return context;
 }
 
+//static
+LLVector2& LLUI::getScaleFactor()
+{
+    return LLRender::sUIGLScaleFactor;
+}
+
+//static
+void LLUI::setScaleFactor(const LLVector2& scale_factor)
+{
+    LLRender::sUIGLScaleFactor = scale_factor;
+}
+
 
 // LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
 
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 9856e551cc..238bef3bf8 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -313,14 +313,14 @@ public:
 	void positionViewNearMouse(LLView* view,	S32 spawn_x = S32_MAX, S32 spawn_y = S32_MAX);
 
 	// LLRender2D wrappers
-	static void pushMatrix() { LLRender2D::getInstance()->pushMatrix(); }
-	static void popMatrix() { LLRender2D::getInstance()->popMatrix(); }
-	static void loadIdentity() { LLRender2D::getInstance()->loadIdentity(); }
-	static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::getInstance()->translate(x, y, z); }
-
-	static LLVector2& getScaleFactor() { return LLRender2D::getInstance()->mGLScaleFactor; }
-	static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::getInstance()->setScaleFactor(scale_factor); }
-	static void setLineWidth(F32 width) { LLRender2D::getInstance()->setLineWidth(width); }
+	static void pushMatrix() { LLRender2D::pushMatrix(); }
+	static void popMatrix() { LLRender2D::popMatrix(); }
+	static void loadIdentity() { LLRender2D::loadIdentity(); }
+	static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); }
+
+    static LLVector2& getScaleFactor();
+    static void setScaleFactor(const LLVector2& scale_factor);
+	static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); }
 	static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0)
 		{ return LLRender2D::getInstance()->getUIImageByID(image_id, priority); }
 	static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0)
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
index 81d862a827..fa89d3986d 100644
--- a/indra/newview/llhudnametag.cpp
+++ b/indra/newview/llhudnametag.cpp
@@ -105,6 +105,9 @@ LLHUDNameTag::LLHUDNameTag(const U8 type)
 {
 	LLPointer<LLHUDNameTag> ptr(this);
 	sTextObjects.insert(ptr);
+
+    mRoundedRectImgp = LLUI::getUIImage("Rounded_Rect");
+    mRoundedRectTopImgp = LLUI::getUIImage("Rounded_Rect_Top");
 }
 
 LLHUDNameTag::~LLHUDNameTag()
@@ -274,9 +277,6 @@ void LLHUDNameTag::renderText(BOOL for_select)
 
 	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
 
-	// *TODO: cache this image
-	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect");
-
 	// *TODO: make this a per-text setting
 	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");
 	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
@@ -306,17 +306,16 @@ void LLHUDNameTag::renderText(BOOL for_select)
 	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
 	LLRect screen_rect;
 	screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight)));
-	imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color);
+    mRoundedRectImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color);
 	if (mLabelSegments.size())
 	{
-		LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top");
 		LLRect label_top_rect = screen_rect;
 		const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f)));
 		label_top_rect.mBottom = label_top_rect.mTop - label_height;
 		LLColor4 label_top_color = text_color;
 		label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor;
 
-		rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);
+        mRoundedRectTopImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);
 	}
 
 	F32 y_offset = (F32)mOffsetY;
diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h
index 38a4f18415..f7d7c2a51a 100644
--- a/indra/newview/llhudnametag.h
+++ b/indra/newview/llhudnametag.h
@@ -40,8 +40,8 @@
 #include <set>
 #include <vector>
 
-class LLDrawable;
 class LLHUDNameTag;
+class LLUIImage;
 
 struct llhudnametag_further_away
 {
@@ -171,6 +171,8 @@ private:
 	EVertAlignment	mVertAlignment;
 	S32				mLOD;
 	BOOL			mHidden;
+	LLPointer<LLUIImage> mRoundedRectImgp;
+	LLPointer<LLUIImage> mRoundedRectTopImgp;
 
 	static BOOL    sDisplayText ;
 	static std::set<LLPointer<LLHUDNameTag> > sTextObjects;
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 82824861a9..98ce632254 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -138,9 +138,6 @@ void LLHUDText::renderText()
 
 	mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
 
-	// *TODO: cache this image
-	LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
-
 	// *TODO: make this a per-text setting
 	LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor");
 	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
-- 
cgit v1.2.3


From a5c8b1cbe20c2ccd609f550ff4983741f622fc27 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 17 Sep 2020 20:34:58 +0300
Subject: SL-13729 Performance of LLUI and LLRender2D #2

---
 indra/llui/llconsole.cpp         | 4 +++-
 indra/llui/llfloater.cpp         | 6 ++++--
 indra/llui/llfolderview.cpp      | 7 +++++--
 indra/llui/llfolderviewmodel.cpp | 5 +++--
 indra/llui/lltoolbar.cpp         | 2 +-
 indra/llui/lltooltip.cpp         | 4 ++--
 indra/llui/llurlentry.cpp        | 2 +-
 indra/llui/llview.cpp            | 8 +++++---
 indra/newview/lltoolpie.cpp      | 3 ++-
 9 files changed, 26 insertions(+), 15 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 7817d99aef..de09fdbafd 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -180,7 +180,9 @@ void LLConsole::draw()
 
 	LLUIImagePtr imagep = LLUI::getUIImage("transparent");
 
-	F32 console_opacity = llclamp(LLUI::getInstance()->mSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
+	static LLCachedControl<F32> console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f);
+	F32 console_opacity = llclamp((F32)console_bg_opacity, 0.f, 1.f);
+
 	LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
 	color.mV[VALPHA] *= console_opacity;
 
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index abb043f428..5ea4a36a6c 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -378,13 +378,15 @@ void LLFloater::layoutDragHandle()
 // static
 void LLFloater::updateActiveFloaterTransparency()
 {
-    sActiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("ActiveFloaterTransparency");
+    static LLCachedControl<F32> active_transparency(*LLUI::getInstance()->mSettingGroups["config"], "ActiveFloaterTransparency", 1.f);
+    sActiveControlTransparency = active_transparency;
 }
 
 // static
 void LLFloater::updateInactiveFloaterTransparency()
 {
-    sInactiveControlTransparency = LLUI::getInstance()->mSettingGroups["config"]->getF32("InactiveFloaterTransparency");
+    static LLCachedControl<F32> inactive_transparency(*LLUI::getInstance()->mSettingGroups["config"], "InactiveFloaterTransparency", 0.95f);
+    sInactiveControlTransparency = inactive_transparency;
 }
 
 void LLFloater::addResizeCtrls()
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index e718fcec46..483862298c 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -342,7 +342,9 @@ static LLTrace::BlockTimerStatHandle FTM_FILTER("Filter Folder View");
 void LLFolderView::filter( LLFolderViewFilter& filter )
 {
 	LL_RECORD_BLOCK_TIME(FTM_FILTER);
-    filter.resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32(mParentPanel.get()->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100));
+    static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+    static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
+    filter.resetTime(llclamp((S32)(mParentPanel.get()->getVisible() ? time_visible : time_invisible), 1, 100));
 
     // Note: we filter the model, not the view
 	getViewModelItem()->filter(filter);
@@ -661,7 +663,8 @@ void LLFolderView::draw()
 		closeAutoOpenedFolders();
 	}
 
-	if (mSearchTimer.getElapsedTimeF32() > LLUI::getInstance()->mSettingGroups["config"]->getF32("TypeAheadTimeout") || !mSearchString.size())
+	static LLCachedControl<F32> type_ahead_timeout(*LLUI::getInstance()->mSettingGroups["config"], "TypeAheadTimeout", 1.5f);
+	if (mSearchTimer.getElapsedTimeF32() > type_ahead_timeout || !mSearchString.size())
 	{
 		mSearchString.clear();
 	}
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index 3b45fb53a2..a91c3e07d4 100644
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,8 +48,9 @@ std::string LLFolderViewModelCommon::getStatusText()
 
 void LLFolderViewModelCommon::filter()
 {
-    getFilter().resetTime(llclamp(LLUI::getInstance()->mSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));
-	mFolderView->getViewModelItem()->filter(getFilter());
+    static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
+    getFilter().resetTime(llclamp((S32)max_time, 1, 100));
+    mFolderView->getViewModelItem()->filter(getFilter());
 }
 
 bool LLFolderViewModelItemCommon::hasFilterStringMatch()
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index e6f466ec78..0961db37ba 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -1125,7 +1125,7 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask)
 	BOOL handled = FALSE;
 		
 	S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY);
-	S32 drag_threshold = LLUI::getInstance()->mSettingGroups["config"]->getS32("DragAndDropDistanceThreshold");
+	static LLCachedControl<S32> drag_threshold(*LLUI::getInstance()->mSettingGroups["config"], "DragAndDropDistanceThreshold", 3);
 	if (mouse_distance_squared > drag_threshold * drag_threshold
 		&& hasMouseCapture() && 
 		mStartDragItemCallback && mHandleDragItemCallback)
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 422534b781..1262e8a820 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -358,8 +358,8 @@ void LLToolTip::draw()
 
 	if (mFadeTimer.getStarted())
 	{
-		F32 tool_tip_fade_time = LLUI::getInstance()->mSettingGroups["config"]->getF32("ToolTipFadeTime");
-		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time, 1.f, 0.f);
+		static LLCachedControl<F32> tool_tip_fade_time(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFadeTime", 0.2f);
+		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, (F32)tool_tip_fade_time, 1.f, 0.f);
 		if (alpha == 0.f)
 		{
 			// finished fading out, so hide ourselves
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 333d03f208..3609f3b238 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -176,7 +176,7 @@ void LLUrlEntryBase::callObservers(const std::string &id,
 bool LLUrlEntryBase::isLinkDisabled() const
 {
 	// this allows us to have a global setting to turn off text hyperlink highlighting/action
-	bool globally_disabled = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("DisableTextHyperlinkActions");
+	static LLCachedControl<bool> globally_disabled(*LLUI::getInstance()->mSettingGroups["config"], "DisableTextHyperlinkActions", false);
 
 	return globally_disabled;
 }
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index bd213d594a..8b889376b8 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -875,14 +875,16 @@ BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
 	std::string tooltip = getToolTip();
 	if (!tooltip.empty())
 	{
+        static LLCachedControl<F32> tooltip_fast_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFastDelay", 0.1f);
+        static LLCachedControl<F32> tooltip_delay(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipDelay", 0.7f);
+        static LLCachedControl<bool> allow_ui_tooltips(*LLUI::getInstance()->mSettingGroups["config"], "BasicUITooltips", true);
 		// allow "scrubbing" over ui by showing next tooltip immediately
 		// if previous one was still visible
 		F32 timeout = LLToolTipMgr::instance().toolTipVisible() 
-		              ? LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipFastDelay" )
-		              : LLUI::getInstance()->mSettingGroups["config"]->getF32( "ToolTipDelay" );
+		              ? tooltip_fast_delay
+		              : tooltip_delay;
 
 		// Even if we don't show tooltips, consume the event, nothing below should show tooltip
-		bool allow_ui_tooltips = LLUI::getInstance()->mSettingGroups["config"]->getBOOL("BasicUITooltips");
 		if (allow_ui_tooltips)
 		{
 			LLToolTipMgr::instance().show(LLToolTip::Params()
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index f499c34ca4..7d7cf23822 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -1249,7 +1249,8 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
 
 BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
 {
-	if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
+	static LLCachedControl<bool> show_hover_tips(*LLUI::getInstance()->mSettingGroups["config"], "ShowHoverTips", true);
+	if (!show_hover_tips) return TRUE;
 	if (!mHoverPick.isValid()) return TRUE;
 
 	LLViewerObject* hover_object = mHoverPick.getObject();
-- 
cgit v1.2.3


From 0d7f6d917af2e0b19a32a925ded6fab4b1a6725e Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 18 Sep 2020 16:57:57 +0300
Subject: SL-13729 Performance of LLUI and LLRender2D #3

---
 indra/llui/llaccordionctrltab.cpp |  2 +-
 indra/llui/llconsole.cpp          |  2 +-
 indra/llui/llfolderview.cpp       |  2 +-
 indra/llui/llfolderviewmodel.cpp  |  2 +-
 indra/llui/lltooltip.cpp          |  2 +-
 indra/llui/llui.cpp               | 14 --------------
 indra/llui/llui.h                 |  4 ----
 indra/llui/llview.cpp             | 14 ++++++++++++--
 indra/llui/llview.h               |  3 +++
 indra/newview/llviewerdisplay.cpp | 33 ++++++++++++++++-----------------
 indra/newview/llviewerwindow.cpp  |  2 +-
 11 files changed, 37 insertions(+), 43 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 1034a21905..16ca578111 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -977,7 +977,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)
 		LLRect screen_rect;
 		localRectToScreen(child->getRect(),&screen_rect);
 		
-		if ( root_rect.overlaps(screen_rect)  && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect))
+		if ( root_rect.overlaps(screen_rect)  && sDirtyRect.overlaps(screen_rect))
 		{
 			gGL.matrixMode(LLRender::MM_MODELVIEW);
 			LLUI::pushMatrix();
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index de09fdbafd..8fc2978bdd 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -181,7 +181,7 @@ void LLConsole::draw()
 	LLUIImagePtr imagep = LLUI::getUIImage("transparent");
 
 	static LLCachedControl<F32> console_bg_opacity(*LLUI::getInstance()->mSettingGroups["config"], "ConsoleBackgroundOpacity", 0.7f);
-	F32 console_opacity = llclamp((F32)console_bg_opacity, 0.f, 1.f);
+	F32 console_opacity = llclamp(console_bg_opacity(), 0.f, 1.f);
 
 	LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
 	color.mV[VALPHA] *= console_opacity;
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index 483862298c..622c9edba7 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -344,7 +344,7 @@ void LLFolderView::filter( LLFolderViewFilter& filter )
 	LL_RECORD_BLOCK_TIME(FTM_FILTER);
     static LLCachedControl<S32> time_visible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
     static LLCachedControl<S32> time_invisible(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameUnvisible", 1);
-    filter.resetTime(llclamp((S32)(mParentPanel.get()->getVisible() ? time_visible : time_invisible), 1, 100));
+    filter.resetTime(llclamp((mParentPanel.get()->getVisible() ? time_visible() : time_invisible()), 1, 100));
 
     // Note: we filter the model, not the view
 	getViewModelItem()->filter(filter);
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index a91c3e07d4..93122503d1 100644
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -49,7 +49,7 @@ std::string LLFolderViewModelCommon::getStatusText()
 void LLFolderViewModelCommon::filter()
 {
     static LLCachedControl<S32> max_time(*LLUI::getInstance()->mSettingGroups["config"], "FilterItemsMaxTimePerFrameVisible", 10);
-    getFilter().resetTime(llclamp((S32)max_time, 1, 100));
+    getFilter().resetTime(llclamp(max_time(), 1, 100));
     mFolderView->getViewModelItem()->filter(getFilter());
 }
 
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 1262e8a820..2f56a8b1d0 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -359,7 +359,7 @@ void LLToolTip::draw()
 	if (mFadeTimer.getStarted())
 	{
 		static LLCachedControl<F32> tool_tip_fade_time(*LLUI::getInstance()->mSettingGroups["config"], "ToolTipFadeTime", 0.2f);
-		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, (F32)tool_tip_fade_time, 1.f, 0.f);
+		alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, tool_tip_fade_time(), 1.f, 0.f);
 		if (alpha == 0.f)
 		{
 			// finished fading out, so hide ourselves
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 77b59e5bc5..6f16745bd3 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -154,7 +154,6 @@ mAudioCallback(audio_callback),
 mDeferredAudioCallback(deferred_audio_callback),
 mWindow(NULL), // set later in startup
 mRootView(NULL),
-mDirty(FALSE),
 mHelpImpl(NULL)
 {
 	LLRender2D::initParamSingleton(image_provider);
@@ -203,19 +202,6 @@ void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& rem
 	mClearPopupsFunc = clear_popups;
 }
 
-void LLUI::dirtyRect(LLRect rect)
-{
-	if (!mDirty)
-	{
-		mDirtyRect = rect;
-		mDirty = TRUE;
-	}
-	else
-	{
-		mDirtyRect.unionWith(rect);
-	}
-}
-
 void LLUI::setMousePositionScreen(S32 x, S32 y)
 {
 #if defined(LL_DARWIN)
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 238bef3bf8..30dbd7248f 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -245,10 +245,6 @@ public:
 
 	void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& );
 
-	LLRect	mDirtyRect;
-	BOOL		mDirty;
-	void		dirtyRect(LLRect rect);
-
 	// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.
 	// http://www.loc.gov/standards/iso639-2/php/code_list.php
 	std::string getUILanguage();
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 8b889376b8..f8686018b8 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -60,6 +60,8 @@ static const S32 LINE_HEIGHT = 15;
 
 S32		LLView::sDepth = 0;
 bool	LLView::sDebugRects = false;
+bool	LLView::sIsRectDirty = false;
+LLRect	LLView::sDirtyRect;
 bool	LLView::sDebugRectsShowNames = true;
 bool	LLView::sDebugKeys = false;
 bool	LLView::sDebugMouseHandling = false;
@@ -1181,7 +1183,7 @@ void LLView::drawChildren()
 			if (viewp->getVisible() && viewp->getRect().isValid())
 			{
 				LLRect screen_rect = viewp->calcScreenRect();
-				if ( rootp->getLocalRect().overlaps(screen_rect)  && LLUI::getInstance()->mDirtyRect.overlaps(screen_rect))
+				if ( rootp->getLocalRect().overlaps(screen_rect)  && sDirtyRect.overlaps(screen_rect))
 				{
 					LLUI::pushMatrix();
 					{
@@ -1223,7 +1225,15 @@ void LLView::dirtyRect()
 		parent = parent->getParent();
 	}
 
-	LLUI::getInstance()->dirtyRect(cur->calcScreenRect());
+    if (!sIsRectDirty)
+    {
+        sDirtyRect = cur->calcScreenRect();
+        sIsRectDirty = true;
+    }
+    else
+    {
+        sDirtyRect.unionWith(cur->calcScreenRect());
+    }
 }
 
 //Draw a box for debugging.
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index db81900aaf..7c90794ddb 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -656,6 +656,9 @@ public:
 	// Draw debug rectangles around widgets to help with alignment and spacing
 	static bool	sDebugRects;
 
+    static bool sIsRectDirty;
+    static LLRect sDirtyRect;
+
 	// Draw widget names and sizes when drawing debug rectangles, turning this
 	// off is useful to make the rectangles themselves easier to see.
 	static bool sDebugRectsShowNames;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index f025863072..b4361b3968 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1524,10 +1524,9 @@ void render_ui_2d()
 
 	if (gSavedSettings.getBOOL("RenderUIBuffer"))
 	{
-		LLUI* ui_inst = LLUI::getInstance();
-		if (ui_inst->mDirty)
+		if (LLView::sIsRectDirty)
 		{
-			ui_inst->mDirty = FALSE;
+            LLView::sIsRectDirty = false;
 			LLRect t_rect;
 
 			gPipeline.mUIScreen.bindTarget();
@@ -1535,25 +1534,25 @@ void render_ui_2d()
 			{
 				static const S32 pad = 8;
 
-				ui_inst->mDirtyRect.mLeft -= pad;
-				ui_inst->mDirtyRect.mRight += pad;
-				ui_inst->mDirtyRect.mBottom -= pad;
-				ui_inst->mDirtyRect.mTop += pad;
+                LLView::sDirtyRect.mLeft -= pad;
+                LLView::sDirtyRect.mRight += pad;
+                LLView::sDirtyRect.mBottom -= pad;
+                LLView::sDirtyRect.mTop += pad;
 
 				LLGLEnable scissor(GL_SCISSOR_TEST);
-				static LLRect last_rect = ui_inst->mDirtyRect;
+				static LLRect last_rect = LLView::sDirtyRect;
 
 				//union with last rect to avoid mouse poop
-				last_rect.unionWith(ui_inst->mDirtyRect);
+				last_rect.unionWith(LLView::sDirtyRect);
 								
-				t_rect = ui_inst->mDirtyRect;
-				ui_inst->mDirtyRect = last_rect;
+				t_rect = LLView::sDirtyRect;
+                LLView::sDirtyRect = last_rect;
 				last_rect = t_rect;
-			
-				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / ui_inst->getScaleFactor().mV[0]);
-				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / ui_inst->getScaleFactor().mV[0]);
-				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / ui_inst->getScaleFactor().mV[1]);
-				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / ui_inst->getScaleFactor().mV[1]);
+
+				last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]);
+				last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]);
+				last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]);
+				last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]);
 
 				LLRect clip_rect(last_rect);
 				
@@ -1565,7 +1564,7 @@ void render_ui_2d()
 			gPipeline.mUIScreen.flush();
 			gGL.setColorMask(true, false);
 
-			ui_inst->mDirtyRect = t_rect;
+            LLView::sDirtyRect = t_rect;
 		}
 
 		LLGLDisable cull(GL_CULL_FACE);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0cc1e0df06..85c8b42da9 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2580,7 +2580,7 @@ void LLViewerWindow::draw()
 
 	if (!gSavedSettings.getBOOL("RenderUIBuffer"))
 	{
-		LLUI::getInstance()->mDirtyRect = getWindowRectScaled();
+		LLView::sDirtyRect = getWindowRectScaled();
 	}
 
 	// HACK for timecode debugging
-- 
cgit v1.2.3


From 531349a2fef9476d7afb12e7b5efa8e984e11000 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 21 Sep 2020 14:26:27 +0300
Subject: SL-13729 Small fix with some cached settings

---
 indra/newview/llvovolume.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e23b54f60c..93062b7a2e 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5429,8 +5429,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	U32 useage = group->getSpatialPartition()->mBufferUsage;
 
-	LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
-	LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536);
+	static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
+	static LLCachedControl<S32> max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536);
 	U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
 	U32 max_total = (max_node_size * 1024) / LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
 	max_vertices = llmin(max_vertices, (U32) 65535);
@@ -6195,7 +6195,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 #endif
 	
 	//calculate maximum number of vertices to store in a single buffer
-	LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
+	static LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
 	U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask);
 	max_vertices = llmin(max_vertices, (U32) 65535);
 
-- 
cgit v1.2.3


From f6bc93ceed7d462b232ce2711a7525bb71e5f691 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 22 Sep 2020 19:27:46 +0300
Subject: SL-13971 [Cleanup] Viewer complains about missing VertexShaderEnable

---
 indra/newview/app_settings/settings.xml                 | 13 -------------
 indra/newview/featuretable.txt                          | 11 -----------
 indra/newview/featuretable_linux.txt                    | 11 -----------
 indra/newview/featuretable_mac.txt                      | 11 -----------
 .../xui/en/floater_preferences_graphics_advanced.xml    | 17 -----------------
 5 files changed, 63 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a00aa86d78..e816eed3e0 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14316,19 +14316,6 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
-    <!-- SL-12594 removes fixed function rendering
-    <key>VertexShaderEnable</key>
-    <map>
-      <key>Comment</key>
-      <string>Enable/disable all GLSL shaders (debug)</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>Boolean</string>
-      <key>Value</key>
-      <integer>0</integer>
-    </map>
-    <-->
     <key>VivoxAutoPostCrashDumps</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index e6ee458719..f1bf8d76c2 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 Disregard128DefaultDrawDistance	1	1
@@ -95,7 +94,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -127,7 +125,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -158,7 +155,6 @@ RenderTerrainLODFactor		1	1.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -189,7 +185,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -220,7 +215,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	0
@@ -251,7 +245,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -282,7 +275,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -312,7 +304,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderVolumeLODFactor		1	2.0
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
@@ -380,7 +371,6 @@ list NoPixelShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
@@ -394,7 +384,6 @@ list NoVertexShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index bc836a99ca..5542eee6ca 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 Disregard128DefaultDrawDistance	1	1
@@ -94,7 +93,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -126,7 +124,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -157,7 +154,6 @@ RenderTerrainLODFactor		1	1.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -188,7 +184,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -219,7 +214,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderUseAdvancedAtmospherics 1 0
@@ -250,7 +244,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -281,7 +274,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -311,7 +303,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderVolumeLODFactor		1	2.0
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
@@ -379,7 +370,6 @@ list NoPixelShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
@@ -393,7 +383,6 @@ list NoVertexShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 68202a571f..bac6fd5708 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -56,7 +56,6 @@ RenderVBOMappingDisable		1	1
 RenderVolumeLODFactor		1	2.0
 UseStartScreen				1	1
 UseOcclusion				1	1
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 Disregard128DefaultDrawDistance	1	1
@@ -95,7 +94,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	0.5
-VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -127,7 +125,6 @@ RenderTerrainLODFactor		1	1
 RenderTransparentWater		1	0
 RenderTreeLODFactor			1	0
 RenderVolumeLODFactor		1	0.5
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -158,7 +155,6 @@ RenderTerrainLODFactor		1	1.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -189,7 +185,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
@@ -220,7 +215,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	0
@@ -251,7 +245,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -282,7 +275,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.125
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
@@ -312,7 +304,6 @@ RenderTerrainLODFactor		1	2.0
 RenderTransparentWater		1	1
 RenderTreeLODFactor			1	1.0
 RenderVolumeLODFactor		1	2.0
-VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
@@ -374,7 +365,6 @@ list NoPixelShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
@@ -388,7 +378,6 @@ list NoVertexShaders
 RenderAvatarVP				0	0
 RenderAvatarCloth			0	0
 RenderReflectionDetail		0	0
-VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index e93568a87e..131d0024a0 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -623,23 +623,6 @@
     top_delta="16"
     width="300" />
 
-  <!-- SL-12594, basic shaders always enabled, no fixed-function GL 
-  <check_box
-    control_name="VertexShaderEnable"
-    height="16"
-    initial_value="true"
-    label="Basic shaders"
-    layout="topleft"
-    left="420"
-    name="BasicShaders"
-    tool_tip="Disabling this option may prevent some graphics card drivers from crashing"
-    top_delta="16"
-    width="300">
-    <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
-  </check_box>
-  -->
-    
   <slider
     control_name="RenderTerrainDetail"
     follows="left|top"
-- 
cgit v1.2.3


From 74f8fd572164ba84f3b4e47a83c93b56f6fc91fc Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:27:38 +0300
Subject: Revert "SL-13814 Updated label text"

This reverts commit 1557cd8fe2733c32c7788daf752fe23c7190947f.
---
 indra/newview/llfloaterbuycurrency.cpp         |  7 ++-----
 indra/newview/llviewermenu.cpp                 |  2 +-
 indra/newview/llviewermenufile.cpp             | 10 ++++++++--
 indra/newview/skins/default/xui/en/strings.xml |  8 ++++----
 4 files changed, 15 insertions(+), 12 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index dfc755c370..b183ba6912 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -59,6 +59,7 @@ public:
 	LLCurrencyUIManager	mManager;
 	
 	bool		mHasTarget;
+	std::string	mTargetName;
 	S32			mTargetPrice;
 	S32			mRequiredAmount;
 	
@@ -115,13 +116,9 @@ void LLFloaterBuyCurrencyUI::noTarget()
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 {
 	mHasTarget = true;
+	mTargetName = name;
 	mTargetPrice = price;
 	
-	if (!name.empty())
-	{
-		getChild<LLUICtrl>("target_price_label")->setValue(name);
-	}
-
 	S32 balance = gStatusBar->getBalance();
 	S32 need = price - balance;
 	if (need < 0)
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 546d8e5377..b333b94462 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -4897,7 +4897,7 @@ void handle_buy_or_take()
 		{
 			LLStringUtil::format_map_t args;
 			args["AMOUNT"] = llformat("%d", total_price);
-			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price );
+			LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "BuyingCosts", args ), total_price );
 		}
 	}
 	else
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 7d52607cba..cd48b1e8e7 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -825,7 +825,10 @@ void upload_done_callback(
 				
 				if(!(can_afford_transaction(expected_upload_cost)))
 				{
-					LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost );
+					LLStringUtil::format_map_t args;
+					args["NAME"] = data->mAssetInfo.getName();
+					args["AMOUNT"] = llformat("%d", expected_upload_cost);
+					LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost );
 					is_balance_sufficient = FALSE;
 				}
 				else if(region)
@@ -959,7 +962,10 @@ void upload_new_resource(
 			if (balance < uploadInfo->getExpectedUploadCost())
 			{
 				// insufficient funds, bail on this upload
-                LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost());
+				LLStringUtil::format_map_t args;
+				args["NAME"] = uploadInfo->getName();
+                args["AMOUNT"] = llformat("%d", uploadInfo->getExpectedUploadCost());
+                LLBuyCurrencyHTML::openCurrencyFloater(LLTrans::getString("UploadingCosts", args), uploadInfo->getExpectedUploadCost());
 				return;
 			}
 		}
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 3f06d658d7..c9ea423a20 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2833,6 +2833,7 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="AcquiredItems">Acquired Items</string>
 	<string name="Cancel">Cancel</string>
 	<string name="UploadingCosts">Uploading [NAME] costs L$ [AMOUNT]</string>
+	<string name="BuyingCosts">Buying this costs L$ [AMOUNT]</string>
 	<string name="UnknownFileExtension">
 		Unknown file extension .%s
 Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
@@ -3788,12 +3789,11 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
   <string name="to upload">to upload</string>
   <string name="to publish a classified ad">to publish a classified ad</string>
 
+  <string name="giving">Giving L$ [AMOUNT]</string>
   <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
   <string name="this_costs">This costs L$ [AMOUNT]</string>
-  
-  <string name="buying_selected_land">This land costs</string>
-  <string name="this_object_costs">This item costs</string>
-  <string name="giving">You want to give</string>
+  <string name="buying_selected_land">Buying selected land for L$ [AMOUNT]</string>
+  <string name="this_object_costs">This object costs L$ [AMOUNT]</string>
 
   <string name="group_role_everyone">Everyone</string>
   <string name="group_role_officers">Officers</string>
-- 
cgit v1.2.3


From f51c6608e1eb6cc5c05e97a558f48bc9fc6ea746 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:28:15 +0300
Subject: Revert "SL-13814 mac build fix"

This reverts commit 85d90ce6bda00f1cb6fc8f0a75e739f1273843b3.
---
 indra/newview/llfloaterbuycurrency.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b183ba6912..b039475389 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -44,6 +44,7 @@
 #include "llwindow.h"
 #include "llappviewer.h"
 
+static const S32 STANDARD_BUY_AMOUNT = 2000;
 static const S32 MINIMUM_BALANCE_AMOUNT = 0;
 
 class LLFloaterBuyCurrencyUI
-- 
cgit v1.2.3


From fc7b5186944412d3f2125923aebf921730a79d20 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:28:34 +0300
Subject: Revert "SL-13814 Clarify dialog for insufficient L$ balance"

This reverts commit f150600ffb17232bfa88a6225aab437460fc9520.
---
 indra/newview/llcurrencyuimanager.cpp              |   7 +-
 indra/newview/llfloaterbuycurrency.cpp             |  61 +-
 .../skins/default/xui/en/floater_buy_currency.xml  | 624 +++++++++------------
 3 files changed, 276 insertions(+), 416 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index cd7332c4d4..df94e337da 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -454,7 +454,7 @@ void LLCurrencyUIManager::Impl::updateUI()
 		
 		if (!mUserEnteredCurrencyBuy)
 		{
-			if (mUserCurrencyBuy == 0)
+			if (!mZeroMessage.empty() && mUserCurrencyBuy == 0)
 			{
 				lindenAmount->setText(LLStringUtil::null);
 			}
@@ -467,9 +467,8 @@ void LLCurrencyUIManager::Impl::updateUI()
 		}
 	}
 
-	std::string estimated = (mUserCurrencyBuy == 0) ? mPanel.getString("estimated_zero") : getLocalEstimate();
-	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", estimated);
-	mPanel.getChildView("currency_est")->setVisible( hasEstimate() || mUserCurrencyBuy == 0);
+	mPanel.getChild<LLUICtrl>("currency_est")->setTextArg("[LOCALAMOUNT]", getLocalEstimate());
+	mPanel.getChildView("currency_est")->setVisible( hasEstimate() && mUserCurrencyBuy > 0);
 
 	mPanel.getChildView("currency_links")->setVisible( mSupportsInternationalBilling);
 	mPanel.getChildView("exchange_rate_note")->setVisible( mSupportsInternationalBilling);
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index b039475389..25348474a1 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -32,8 +32,6 @@
 #include "llcurrencyuimanager.h"
 #include "llfloater.h"
 #include "llfloaterreg.h"
-#include "lllayoutstack.h"
-#include "lliconctrl.h"
 #include "llnotificationsutil.h"
 #include "llstatusbar.h"
 #include "lltextbox.h"
@@ -62,7 +60,6 @@ public:
 	bool		mHasTarget;
 	std::string	mTargetName;
 	S32			mTargetPrice;
-	S32			mRequiredAmount;
 	
 public:
 	void noTarget();
@@ -71,7 +68,6 @@ public:
 	virtual BOOL postBuild();
 	
 	void updateUI();
-	void collapsePanels(bool collapse);
 
 	virtual void draw();
 	virtual BOOL canClose();
@@ -96,9 +92,7 @@ LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
 LLFloaterBuyCurrencyUI::LLFloaterBuyCurrencyUI(const LLSD& key)
 :	LLFloater(key),
 	mChildren(*this),
-	mManager(*this),
-	mHasTarget(false),
-	mTargetPrice(0)
+	mManager(*this)
 {
 }
 
@@ -110,8 +104,7 @@ LLFloaterBuyCurrencyUI::~LLFloaterBuyCurrencyUI()
 void LLFloaterBuyCurrencyUI::noTarget()
 {
 	mHasTarget = false;
-	mTargetPrice = 0;
-	mManager.setAmount(0);
+	mManager.setAmount(STANDARD_BUY_AMOUNT);
 }
 
 void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
@@ -127,8 +120,7 @@ void LLFloaterBuyCurrencyUI::target(const std::string& name, S32 price)
 		need = 0;
 	}
 	
-	mRequiredAmount = need + MINIMUM_BALANCE_AMOUNT;
-	mManager.setAmount(0);
+	mManager.setAmount(need + MINIMUM_BALANCE_AMOUNT);
 }
 
 
@@ -183,6 +175,7 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
 	getChildView("contacting")->setVisible(FALSE);
+	getChildView("buy_action")->setVisible(FALSE);
 
 	if (hasError)
 	{
@@ -215,8 +208,8 @@ void LLFloaterBuyCurrencyUI::updateUI()
 		{
 			if (mHasTarget)
 			{
-				getChild<LLUICtrl>("target_price")->setTextArg("[AMT]", llformat("%d", mTargetPrice));
-				getChild<LLUICtrl>("required_amount")->setTextArg("[AMT]", llformat("%d", mRequiredAmount));
+				getChildView("buy_action")->setVisible( true);
+				getChild<LLUICtrl>("buy_action")->setTextArg("[ACTION]", mTargetName);
 			}
 		}
 		
@@ -237,40 +230,18 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 		if (mHasTarget)
 		{
-			getChildView("purchase_warning_repurchase")->setVisible( !getChildView("currency_links")->getVisible());
+			if (total >= mTargetPrice)
+			{
+				getChildView("purchase_warning_repurchase")->setVisible( true);
+			}
+			else
+			{
+				getChildView("purchase_warning_notenough")->setVisible( true);
+			}
 		}
 	}
 
-	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError && !getChildView("currency_est")->getVisible());
-}
-
-void LLFloaterBuyCurrencyUI::collapsePanels(bool collapse)
-{
-	LLLayoutPanel* price_panel = getChild<LLLayoutPanel>("layout_panel_price");
-	
-	if (price_panel->isCollapsed() == collapse)
-		return;
-	
-	LLLayoutStack* outer_stack = getChild<LLLayoutStack>("outer_stack");	
-	LLLayoutPanel* required_panel = getChild<LLLayoutPanel>("layout_panel_required");
-	LLLayoutPanel* msg_panel = getChild<LLLayoutPanel>("layout_panel_msg");
-
-	S32 delta_height = price_panel->getRect().getHeight() + required_panel->getRect().getHeight() + msg_panel->getRect().getHeight();
-	delta_height *= (collapse ? -1 : 1);
-
-	LLIconCtrl* icon = getChild<LLIconCtrl>("normal_background");
-	LLRect rect = icon->getRect();
-	icon->setRect(rect.setOriginAndSize(rect.mLeft, rect.mBottom - delta_height, rect.getWidth(), rect.getHeight() + delta_height));
-
-	outer_stack->collapsePanel(price_panel, collapse);
-	outer_stack->collapsePanel(required_panel, collapse);
-	outer_stack->collapsePanel(msg_panel, collapse);
-
-	outer_stack->updateLayout();
-
-	LLRect floater_rect = getRect();
-	floater_rect.mBottom -= delta_height;
-	setShape(floater_rect, false);
+	getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError);
 }
 
 void LLFloaterBuyCurrencyUI::onClickBuy()
@@ -294,7 +265,6 @@ void LLFloaterBuyCurrency::buyCurrency()
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->noTarget();
 	ui->updateUI();
-	ui->collapsePanels(true);
 }
 
 // static
@@ -303,7 +273,6 @@ void LLFloaterBuyCurrency::buyCurrency(const std::string& name, S32 price)
 	LLFloaterBuyCurrencyUI* ui = LLFloaterReg::showTypedInstance<LLFloaterBuyCurrencyUI>("buy_currency");
 	ui->target(name, price);
 	ui->updateUI();
-	ui->collapsePanels(false);
 }
 
 
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index e8e83301be..061af1b67c 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <floater
-
+ legacy_header_height="18"
  can_minimize="false"
- height="285"
+ height="275"
  layout="topleft"
  title="BUY L$"
  name="buy currency"
@@ -17,385 +17,277 @@
      name="info_cannot_buy">
         Unable to Buy
     </floater.string>
-    <floater.string
-     name="estimated_zero">
-        US$ 0.00
-    </floater.string>
     <icon
-     height="245"
+     height="215"
      image_name="Linden_Dollar_Background"
      layout="topleft"
      left="0"
      name="normal_background"
-     top="0"
+     top="17"
      use_draw_context_alpha="false"
      width="350" />
-  <layout_stack
-    animate="false"
-    name="outer_stack"
-    layout="topleft"
-    follows="all"
-    orientation="vertical"
-    left="0"
-    top="0"
-    width="350"
-    height="285">
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_title"
+   <text
+     type="string"
+     length="1"
+     follows="top|left|right"
+     font="SansSerifHuge"
+     layout="topleft"
+     left="20"
+     height="30"
+     top="25"
+     width="340"
+     name="info_need_more">
+        You need more L$
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     height="16"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="35">
-      <text
-       type="string"
-       length="1"
-       follows="top|left|right"
-       font="SansSerifLarge"
-       layout="topleft"
-       left="20"
-       height="30"
-       top="8"
-       width="340"
-       name="info_need_more">
-          You need more L$
-      </text>
-      <text
-       type="string"
-       length="1"
-       follows="top|left|right"
-       font="SansSerifLarge"
-       layout="topleft"
-       left="20"
-       height="30"
-       top="8"
-       width="300"
-       name="info_buying">
-          Buy L$
-      </text>
-      <view_border
-       bevel_style="none"
-       height="0"
-       layout="topleft"
-       left="20"
-       name="text_border"
-       top_delta="25"
-       width="300"/>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_price"
+     top="246"
+     left="15"
+     width="300"
+     name="contacting">
+        Contacting LindeX...
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifHuge"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="18">
-      <text
-       type="string"
-       length="1"
-       follows="top|left"
-       font="SansSerifMedium"
-       height="16"
-       layout="topleft"
-       left="20"
-       name="target_price_label"
-       top_pad="3"
-       width="210">
-          You need
-      </text>
-      <text
-       type="string"
-       length="1"
-       font="SansSerifMedium"
-       follows="top|left"
-       halign="right"
-       height="16"
-       layout="topleft"
-       left="200"
-       name="target_price"
-       top_delta="0"
-       width="120">
-          L$ [AMT]
-      </text>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_balance"
+     left="20"
+     height="30"
+     top="25"
+     width="300"
+     name="info_buying">
+        Buy L$
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifMedium"
+     height="16"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="19">
-      <text
-       type="string"
-       length="1"
-       follows="top|left"
-       font="SansSerifMedium"
-       height="16"
-       layout="topleft"
-       left="20"
-       name="balance_label"
-       top_pad="5"
-       width="210">
-        You now have
-      </text>
-      <text
-       type="string"
-       length="1"
-       font="SansSerifMedium"
-       follows="top|left"
-       halign="right"
-       height="16"
-       layout="topleft"
-       left="200"
-       name="balance_amount"
-       top_delta="0"
-       width="120">
+     left="20"
+     name="balance_label"
+     top="65"
+     width="210">
+        I have
+    </text>
+    <text
+     type="string"
+     length="1"
+     font="SansSerifMedium"
+     follows="top|left"
+     halign="right"
+     height="16"
+     layout="topleft"
+     left="200"
+     name="balance_amount"
+     top_delta="0"
+     width="120">
         L$ [AMT]
-      </text>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_required"
+    </text>
+    <text
+     type="string"
+     length="1"
+     follows="top|left"
+     font="SansSerifMedium"
+     height="16"
+     top="95"
+     layout="topleft"
+     left="20"
+     name="currency_action"
+     width="210">
+        I want to buy
+    </text>
+    <text
+     font="SansSerifMedium"
+     type="string"
+     length="1"
+     follows="left|top"
+     height="16"
+     layout="topleft"
+     top_delta="0"
+     left="217"
+     name="currency_label"
+     width="15">
+      L$
+    </text>
+    <line_editor
+     type="string"
+     max_length_bytes="10"
+     halign="right"
+     font="SansSerifMedium"
+     select_on_focus="true"
+     follows="top|left"
+     top_delta="-7"
+     height="22"
+     label="L$"
+     left_pad="3"
+     name="currency_amt"
+     width="85">
+        1234
+    </line_editor>
+    <text
+     type="string"
+     font="SansSerifMedium"
+     length="1"
+     follows="top|left"
+     height="16"
+     layout="topleft"
+     left="20"
+     top="125"
+     name="buying_label"
+     width="210">
+        For the price
+    </text>
+    <text
+     type="string"
+     length="1"
+     font="SansSerifMedium"
+     text_color="EmphasisColor"
+     follows="top|left"
+     halign="right"
+     height="16"
+     top_delta="0"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="22">
-      <text
-        type="string"
-        length="1"
-        follows="top|left"
-        font="SansSerifMedium"
-        font.style="BOLD"
-        height="16"
-        layout="topleft"
-        left="20"
-        name="required_label"
-        top_pad="6"
-        width="210">
-        You should buy at least
-      </text>
-      <text
-       type="string"
-       length="1"
-       font="SansSerifMedium"
-       follows="top|left"
-       halign="right"
-       height="16"
-       layout="topleft"
-       left="200"
-       name="required_amount"
-       top_delta="0"
-       width="120">
+     left="150"
+     name="currency_est"
+     width="170">
+     approx. [LOCALAMOUNT]
+    </text>
+    <text
+     type="string"
+     font="SansSerifSmall"
+     text_color="EmphasisColor"
+     length="1"
+     follows="top|left"
+     height="16"
+     layout="topleft"
+     top="125"
+     left="170"
+     width="150"
+     halign="right"
+     name="getting_data">
+        Estimating...
+    </text>
+    <text
+     type="string"
+     font="SansSerifSmall"
+     top="145"
+     length="1"
+     follows="top|left"
+     height="16"
+     halign="right"
+     left="20"
+     width="300"
+     layout="topleft"
+     name="buy_action">
+        [ACTION]
+    </text>
+    <text
+     type="string"
+     font="SansSerifMedium"
+     length="1"
+     follows="top|left"
+     height="16"
+     layout="topleft"
+     left="20"
+     name="total_label"
+     top="165"
+     width="210">
+        My new balance will be
+    </text>
+    <text
+     type="string"
+     length="1"
+     font="SansSerifMedium"
+     follows="top|left"
+     top_delta="0"
+     height="16"
+     layout="topleft"
+     left="200"
+     halign="right"
+     name="total_amount"
+     width="120">
         L$ [AMT]
-      </text>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_action"
+    </text>
+    <text
+     type="string"
+     length="1"
+     text_color="LtGray_50"
+     follows="top|left"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="90">
-      <view_border
-       bevel_style="none"
-       height="0"
-       layout="topleft"
-       left="20"
-       name="text_border_2"
-       top_pad="5"
-       width="300"/>
-      <text
-       type="string"
-       length="1"
-       follows="top|left"
-       font="SansSerifMedium"
-       height="16"
-       top_pad="15"
-       layout="topleft"
-       left="20"
-       name="currency_action"
-       width="210">
-          Choose amount to buy
-      </text>
-      <text
-       font="SansSerifMedium"
-       type="string"
-       length="1"
-       follows="left|top"
-       height="16"
-       layout="topleft"
-       top_delta="0"
-       left="247"
-       name="currency_label"
-       width="15">
-        L$
-      </text>
-      <line_editor
-       type="string"
-       max_length_bytes="10"
-       halign="right"
-       font="SansSerifMedium"
-       select_on_focus="true"
-       follows="top|left"
-       top_delta="-4"
-       height="22"
-       label="L$"
-       left_pad="3"
-       name="currency_amt"
-       width="55">
-          1234
-      </line_editor>
-      <text
-       type="string"
-       length="1"
-       font="SansSerifMedium"
-       text_color="EmphasisColor"
-       follows="top|left"
-       halign="right"
-       height="16"
-       top_pad="4"
-       layout="topleft"
-       left="150"
-       name="currency_est"
-       width="170">
-       Approx. [LOCALAMOUNT]
-      </text>
-      <text
-       type="string"
-       font="SansSerifSmall"
-       text_color="EmphasisColor"
-       length="1"
-       follows="top|left"
-       height="16"
-       layout="topleft"
-       left="170"
-       top_delta="0"
-       width="150"
-       halign="right"
-       name="getting_data">
-          Estimating...
-      </text>
-      <text
-       type="string"
-       font="SansSerifMedium"
-       length="1"
-       follows="top|left"
-       height="16"
-       layout="topleft"
-       left="20"
-       name="total_label"
-       top_pad="10"
-       width="210">
-          Your new balance will be
-      </text>
-      <text
-       type="string"
-       length="1"
-       font="SansSerifMedium"
-       follows="top|left"
-       top_delta="0"
-       height="16"
-       layout="topleft"
-       left="200"
-       halign="right"
-       name="total_amount"
-       width="120">
-          L$ [AMT]
-      </text>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_msg"
+     halign="right"
+     top="189"
+     left="20"
+     width="300"
+     height="30"
+     name="currency_links">
+      [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
+    </text>
+    <text
+     type="string"
+     length="1"
+     text_color="LtGray_50"
+     follows="top|left"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="50">
-      <view_border
-       bevel_style="none"
-       height="0"
-       layout="topleft"
-       left="20"
-       name="text_border_3"
-       top_pad="0"
-       width="300"/>
-      <text
-       type="string"
-       length="1"
-       text_color="LtGray_50"
-       follows="top|left"
-       layout="topleft"
-       halign="right"
-       top_pad="3"
-       left="20"
-       width="300"
-       height="30"
-       name="currency_links">
-        [http://www.secondlife.com/my/account/payment_method_management.php payment method] | [http://www.secondlife.com/my/account/currency.php currency]
-      </text>
-      <text
-       type="string"
-       length="1"
-       text_color="LtGray_50"
-       follows="top|left"
-       layout="topleft"
-       halign="right"
-       top="19"
-       left="20"
-       width="300"
-       height="30"
-       name="exchange_rate_note">
+     halign="right"
+     top="202"
+     left="20"
+     width="300"
+     height="30"
+     name="exchange_rate_note">
 Re-enter amount to see the latest exchange rate.
-      </text>
-      <text
-       type="string"
-       length="1"
-       follows="top|left"
-       layout="topleft"
-       font="SansSerifMedium"
-       top="10"
-       left="20"
-       width="310"
-       height="35"
-       name="purchase_warning_repurchase">
-After you receive your L$, you should try your
-purchase again.
-      </text>
-    </layout_panel>
-    <layout_panel
-     auto_resize="false"
-     name="layout_panel_buttons"
+    </text>
+    <text
+     type="string"
+     length="1"
+     text_color="LtGray_50"
+     follows="top|left"
+     layout="topleft"
+     halign="right"
+     top="208"
+     left="10"
+     width="310"
+     height="35"
+     name="purchase_warning_repurchase">
+        Confirming this purchase only buys L$, not the object.
+    </text>
+    <text
+     type="string"
+     length="1"
+     text_color="LtGray_50"
+     follows="top|left"
+     layout="topleft"
+     halign="right"
+     top="213"
+     left="20"
+     width="300"
+     height="30"
+     name="purchase_warning_notenough">
+        You aren&apos;t buying enough L$. Please increase the amount.
+    </text>
+
+    <button
+     follows="bottom|left"
+     height="20"
+     label="Buy Now"
+     layout="topleft"
+     left="151"
+     name="buy_btn"
+     top="242"
+     width="90"/>
+    <button
+     follows="bottom|right"
+     height="20"
+     label="Cancel"
      layout="topleft"
-     follows="all"
-     width="350"
-     height="40">
-      <text
-       type="string"
-       length="1"
-       follows="top|left"
-       height="16"
-       layout="topleft"
-       top_pad="0"
-       left="15"
-       width="300"
-       name="contacting">
-          Contacting LindeX...
-        </text>
-      <button
-       follows="top|left|right"
-       height="20"
-       label="Buy L$ now"
-       layout="topleft"
-       left="151"
-       name="buy_btn"
-       bottom_delta ="8"
-       width="90"/>
-      <button
-       follows="top|left|right"
-       height="20"
-       label="Cancel"
-       layout="topleft"
-       left_pad="10"     
-       name="cancel_btn"
-       width="90"/>
-    </layout_panel>
-  </layout_stack>
+     left_pad="10"
+     name="cancel_btn"
+     width="90"/>
 </floater>
-- 
cgit v1.2.3


From d435e2ee26c7a71ee180ebff66bc793b0566e1a2 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:29:54 +0300
Subject: =?UTF-8?q?Revert=20"SL-11867=20Show=20=E2=80=9CUnable=20to=20buy?=
 =?UTF-8?q?=E2=80=9D=20message=20via=20notification"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This reverts commit 7e2e2503c5fb57736844bdad0f309d2d49ee86b2.
---
 indra/newview/llfloaterbuycurrency.cpp             | 37 ++++++++++++++++---
 .../skins/default/xui/da/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/de/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/en/floater_buy_currency.xml  | 42 +++++++++++++++++++---
 .../newview/skins/default/xui/en/notifications.xml | 12 -------
 .../skins/default/xui/es/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/fr/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/it/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/ja/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/pl/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/pt/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/ru/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/tr/floater_buy_currency.xml  |  5 +--
 .../skins/default/xui/zh/floater_buy_currency.xml  |  5 +--
 14 files changed, 103 insertions(+), 43 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index 25348474a1..91436e52fe 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -74,6 +74,7 @@ public:
 
 	void onClickBuy();
 	void onClickCancel();
+	void onClickErrorWeb();
 };
 
 LLFloater* LLFloaterBuyCurrency::buildFloater(const LLSD& key)
@@ -131,6 +132,7 @@ BOOL LLFloaterBuyCurrencyUI::postBuild()
 	
 	getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickBuy, this));
 	getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickCancel, this));
+	getChild<LLUICtrl>("error_web")->setCommitCallback( boost::bind(&LLFloaterBuyCurrencyUI::onClickErrorWeb, this));
 	
 	center();
 	
@@ -171,6 +173,7 @@ void LLFloaterBuyCurrencyUI::updateUI()
 
 	// hide most widgets - we'll turn them on as needed next
 	getChildView("info_buying")->setVisible(FALSE);
+	getChildView("info_cannot_buy")->setVisible(FALSE);
 	getChildView("info_need_more")->setVisible(FALSE);	
 	getChildView("purchase_warning_repurchase")->setVisible(FALSE);
 	getChildView("purchase_warning_notenough")->setVisible(FALSE);
@@ -180,16 +183,32 @@ void LLFloaterBuyCurrencyUI::updateUI()
 	if (hasError)
 	{
 		// display an error from the server
-		LLSD args;
-		args["TITLE"] = getString("info_cannot_buy");
-		args["MESSAGE"] = mManager.errorMessage();
-		LLNotificationsUtil::add("CouldNotBuyCurrency", args);
-		closeFloater();
+		getChildView("normal_background")->setVisible(FALSE);
+		getChildView("error_background")->setVisible(TRUE);
+		getChildView("info_cannot_buy")->setVisible(TRUE);
+		getChildView("cannot_buy_message")->setVisible(TRUE);
+		getChildView("balance_label")->setVisible(FALSE);
+		getChildView("balance_amount")->setVisible(FALSE);
+		getChildView("buying_label")->setVisible(FALSE);
+		getChildView("buying_amount")->setVisible(FALSE);
+		getChildView("total_label")->setVisible(FALSE);
+		getChildView("total_amount")->setVisible(FALSE);
+
+        LLTextBox* message = getChild<LLTextBox>("cannot_buy_message");
+        if (message)
+		{
+			message->setText(mManager.errorMessage());
+		}
+
+		getChildView("error_web")->setVisible( !mManager.errorURI().empty());
 	}
 	else
 	{
 		// display the main Buy L$ interface
 		getChildView("normal_background")->setVisible(TRUE);
+		getChildView("error_background")->setVisible(FALSE);
+		getChildView("cannot_buy_message")->setVisible(FALSE);
+		getChildView("error_web")->setVisible(FALSE);
 
 		if (mHasTarget)
 		{
@@ -259,6 +278,14 @@ void LLFloaterBuyCurrencyUI::onClickCancel()
 	LLStatusBar::sendMoneyBalanceRequest();
 }
 
+void LLFloaterBuyCurrencyUI::onClickErrorWeb()
+{
+	LLWeb::loadURL(mManager.errorURI());
+	closeFloater();
+	// Update L$ balance
+	LLStatusBar::sendMoneyBalanceRequest();
+}
+
 // static
 void LLFloaterBuyCurrency::buyCurrency()
 {
diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
index b7ac181dd4..3c0428b2b0 100644
--- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml
@@ -60,7 +60,8 @@ objektet.
 	</text>
 	<button label="Køb nu" name="buy_btn"/>
 	<button label="Annullér" name="cancel_btn"/>
-  <floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		Kan ikke købe
-	</floater.string>
+	</text>
+	<button label="Fortsæt til web" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_buy_currency.xml b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
index eb94df1cad..65926c088c 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="Jetzt kaufen" name="buy_btn"/>
 	<button label="Abbrechen" name="cancel_btn"/>
-  <floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		Kaufabbruch
-	</floater.string>
+	</text>
+	<button label="Weiter zur Kontoseite" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 061af1b67c..553c5d51d0 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -13,10 +13,6 @@
      name="buy_currency">
         Buy L$ [LINDENS] for approx. [LOCALAMOUNT]
     </floater.string>
-    <floater.string
-     name="info_cannot_buy">
-        Unable to Buy
-    </floater.string>
     <icon
      height="215"
      image_name="Linden_Dollar_Background"
@@ -290,4 +286,42 @@ Re-enter amount to see the latest exchange rate.
      left_pad="10"
      name="cancel_btn"
      width="90"/>
+    <icon
+     height="215"
+     image_name="Linden_Dollar_Alert"
+     layout="topleft"
+     left="0"
+     name="error_background"
+     top="15"
+     use_draw_context_alpha="false"
+     width="350"/>
+    <text
+     type="string"
+     font="SansSerifHuge"
+     left="165"
+     width="360"
+     height="25"
+     top="25"
+     name="info_cannot_buy">
+        Unable to Buy
+    </text>
+     <text
+      type="string"
+      width="176"
+      height="125"
+      top="60"
+      left="165"
+      word_wrap="true"
+      follows="bottom|right"
+      name="cannot_buy_message">
+     </text>
+     <button
+      follows="bottom|left"
+      height="20"
+      label="Continue to the Web"
+      layout="topleft"
+      left="170"
+      name="error_web"
+      top="200"
+      width="160"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 3228603f45..d141cfc313 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1329,18 +1329,6 @@ There was a problem uploading a report screenshot due to the following reason: [
 You must agree to the Second Life Terms and Conditions, Privacy Policy, and Terms of Service to continue logging into [SECOND_LIFE].
   </notification>
 
-  <notification
-   icon="alertmodal.tga"
-   name="CouldNotBuyCurrency"
-   type="alertmodal">
-[TITLE]
-[MESSAGE]
-   <tag>fail</tag>
-   <usetemplate
-     name="okbutton"
-     yestext="OK"/>
-  </notification>
-  
   <notification
    icon="alertmodal.tga"
    name="CouldNotPutOnOutfit"
diff --git a/indra/newview/skins/default/xui/es/floater_buy_currency.xml b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
index 086150dd57..dbff3fcf0e 100644
--- a/indra/newview/skins/default/xui/es/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/es/floater_buy_currency.xml
@@ -60,7 +60,8 @@ no el objeto.
 	</text>
 	<button label="Comprar ahora" name="buy_btn"/>
 	<button label="Cancelar" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy" left="150" font="SansSerifBig">
 		No se pudo hacer la compra
-	</floater.string>
+	</text>
+	<button label="Ir a la web" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index 55b0d1825a..c295172abf 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -60,7 +60,8 @@ le Lindex...
 	</text>
 	<button label="Acheter" name="buy_btn"/>
 	<button label="Annuler" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy" left="160" width="200">
+	<text name="info_cannot_buy" left="160" width="200">
 		Achat impossible
-	</floater.string>
+	</text>
+	<button label="Accéder au Web" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 522d26373e..53a2057455 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -60,7 +60,8 @@ l&apos;oggetto.
 	</text>
 	<button label="Acquista" name="buy_btn"/>
 	<button label="Annulla" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy" left="160" font="SansSerifBig">
+	<text name="info_cannot_buy" left="160" font="SansSerifBig">
 		Non in grado di acquistare
-	</floater.string>
+	</text>
+	<button label="Continua sul Web" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
index ac2db917cc..a472f163e3 100644
--- a/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ja/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="購入する" name="buy_btn"/>
 	<button label="取り消し" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		購入できません
-	</floater.string>
+	</text>
+	<button label="Web サイトに移動" name="error_web" width="140"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
index a1d703a15a..72167e0d3c 100644
--- a/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pl/floater_buy_currency.xml
@@ -50,7 +50,8 @@
 	</text>
 	<button label="Kup teraz" name="buy_btn" />
 	<button label="Anuluj" name="cancel_btn" />
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		Nie można kupić
-	</floater.string>
+	</text>
+	<button label="Odwiedź stronę WWW" name="error_web" />
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
index c740b90472..513400954b 100644
--- a/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/pt/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="Comprar já!" name="buy_btn"/>
 	<button label="Fechar" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy" font="SansSerifBig">
 		Transação incompleta
-	</floater.string>
+	</text>
+	<button label="Prosseguir para a web" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
index ef55ce58d4..87e8bd524e 100644
--- a/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/ru/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="Приобрести" name="buy_btn"/>
 	<button label="Отмена" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		Нельзя купить
-	</floater.string>
+	</text>
+	<button label="Продолжить в Интернете" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
index 33c4b2287f..d90985dcff 100644
--- a/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/tr/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="Şimdi Satın Al" name="buy_btn"/>
 	<button label="İptal" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		Satın Alınamıyor
-	</floater.string>
+	</text>
+	<button label="Web&apos;e devam et" name="error_web"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
index 41c8c26ccc..fcf2800728 100644
--- a/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/zh/floater_buy_currency.xml
@@ -59,7 +59,8 @@
 	</text>
 	<button label="立即購買" name="buy_btn"/>
 	<button label="取消" name="cancel_btn"/>
-	<floater.string name="info_cannot_buy">
+	<text name="info_cannot_buy">
 		無法購買
-	</floater.string>
+	</text>
+	<button label="繼續到網頁" name="error_web"/>
 </floater>
-- 
cgit v1.2.3


From f392ddab9884b97ce9488614cc3fa6f10b8ebdc2 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:30:47 +0300
Subject: Revert "SL-13852 Show menu below the button"

This reverts commit bac27a9d74bc8eb55699aedcf957ba7532ef02c5.
---
 indra/newview/llpanelmaininventory.cpp | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index bcbf92a488..d24440ebbd 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1168,7 +1168,6 @@ void LLPanelMainInventory::initListCommandsHandlers()
 
 	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mVisibilityMenuButton->setMenu(mMenuVisibility);
-	mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT);
 
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
-- 
cgit v1.2.3


From 10a2519e737d2fc4be74e7bb289d0b3eb0709aa0 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:30:59 +0300
Subject: Revert "SL-13852 Add visibility options to inventory search results"

This reverts commit 18566c502398e0e449717a06b1ffae3966e55522.
---
 indra/llui/lllineeditor.h                          |   3 -
 indra/llui/llsearcheditor.cpp                      |  22 +-----
 indra/llui/llsearcheditor.h                        |  20 +----
 indra/newview/llfolderviewmodelinventory.h         |   1 -
 indra/newview/llinventoryfilter.cpp                |  85 +--------------------
 indra/newview/llinventoryfilter.h                  |  17 +----
 indra/newview/llpanelmaininventory.cpp             |  35 ---------
 indra/newview/llpanelmaininventory.h               |   2 -
 .../icons/Inv_Toolbar_SearchVisibility.png         | Bin 756 -> 0 bytes
 indra/newview/skins/default/textures/textures.xml  |   3 -
 .../widgets/TextField_Search_Highlight.png         | Bin 16287 -> 0 bytes
 .../xui/en/menu_inventory_search_visibility.xml    |  44 -----------
 .../skins/default/xui/en/panel_main_inventory.xml  |  40 ++++------
 .../skins/default/xui/en/widgets/filter_editor.xml |   4 +-
 .../skins/default/xui/en/widgets/search_editor.xml |   4 +-
 15 files changed, 22 insertions(+), 258 deletions(-)
 delete mode 100644 indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
 delete mode 100644 indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
 delete mode 100644 indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml

(limited to 'indra')

diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index f84625bea7..aa5779d45f 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -283,9 +283,6 @@ public:
 
 	void			resetContextMenu() { setContextMenu(NULL); };
 
-	void			setBgImage(LLPointer<LLUIImage> image) { mBgImage = image; }
-	void			setBgImageFocused(LLPointer<LLUIImage> image) { mBgImageFocused = image; }
-
 private:
 	// private helper methods
 
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index bafeef41fb..1fdd05a11c 100644
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -34,11 +34,7 @@
 LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 :	LLUICtrl(p),
 	mSearchButton(NULL),
-	mClearButton(NULL),
-	mEditorImage(p.background_image),
-	mEditorImageFocused(p.background_image_focused),
-	mEditorSearchImage(p.background_image_highlight),
-	mHighlightTextField(p.highlight_text_field)
+	mClearButton(NULL)
 {
 	S32 srch_btn_top = p.search_button.top_pad + p.search_button.rect.height;
 	S32 srch_btn_right = p.search_button.rect.width + p.search_button.left_pad;
@@ -61,8 +57,6 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
 	// Set up line editor.
 	LLLineEditor::Params line_editor_params(p);
 	line_editor_params.name("filter edit box");
-	line_editor_params.background_image(p.background_image);
-	line_editor_params.background_image_focused(p.background_image_focused);
 	line_editor_params.rect(getLocalRect());
 	line_editor_params.follows.flags(FOLLOWS_ALL);
 	line_editor_params.text_pad_left(text_pad_left);
@@ -110,20 +104,6 @@ void LLSearchEditor::draw()
 	if (mClearButton)
 		mClearButton->setVisible(!mSearchEditor->getWText().empty());
 
-	if (mHighlightTextField)
-	{	
-		if (!mSearchEditor->getWText().empty())
-		{
-			mSearchEditor->setBgImage(mEditorSearchImage);
-			mSearchEditor->setBgImageFocused(mEditorSearchImage);
-		}
-		else
-		{
-			mSearchEditor->setBgImage(mEditorImage);
-			mSearchEditor->setBgImageFocused(mEditorImageFocused);
-		}
-	}
-
 	LLUICtrl::draw();
 }
 
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index c0f3c1d60c..3b12868225 100644
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -47,23 +47,14 @@ public:
 		Optional<LLButton::Params>	search_button, 
 									clear_button;
 		Optional<bool>				search_button_visible, 
-									clear_button_visible,
-									highlight_text_field;
+									clear_button_visible;
 		Optional<commit_callback_t> keystroke_callback;
 
-		Optional<LLUIImage*>		background_image,
-									background_image_focused,
-									background_image_highlight;
-
 		Params()
 		:	search_button("search_button"),
 			search_button_visible("search_button_visible"),
 			clear_button("clear_button"), 
-			clear_button_visible("clear_button_visible"),
-			highlight_text_field("highlight_text_field"),
-			background_image("background_image"),
-			background_image_focused("background_image_focused"),
-			background_image_highlight("background_image_highlight")
+			clear_button_visible("clear_button_visible")
 		{}
 	};
 
@@ -102,13 +93,6 @@ protected:
 	LLLineEditor* mSearchEditor;
 	LLButton* mSearchButton;
 	LLButton* mClearButton;
-
-	LLPointer<LLUIImage> mEditorImage;
-	LLPointer<LLUIImage> mEditorImageFocused;
-	LLPointer<LLUIImage> mEditorSearchImage;
-	LLPointer<LLUIImage> mEditorSearchImageFocused;
-
-	bool mHighlightTextField;
 };
 
 #endif  // LL_SEARCHEDITOR_H
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 51b98339c4..06a908cccc 100644
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -45,7 +45,6 @@ public:
 	virtual LLFolderType::EType getPreferredType() const = 0;
 	virtual void showProperties(void) = 0;
 	virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make   into pure virtual.
-	virtual BOOL isAgentInventory() const { return FALSE; }
 	virtual BOOL isUpToDate() const = 0;
 	virtual bool hasChildren() const = 0;
 	virtual LLInventoryType::EType getInventoryType() const = 0;
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 1b99c90d5c..8f18de0210 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -63,8 +63,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
 	mPermissions(p.permissions),
 	mFilterTypes(p.types),
 	mFilterUUID(p.uuid),
-	mFilterLinks(p.links),
-	mSearchVisibility(0xffffFFFFffffFFFFULL)
+	mFilterLinks(p.links)
 {
 }
 
@@ -155,7 +154,6 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
 	passed = passed && checkAgainstPermissions(listener);
 	passed = passed && checkAgainstFilterLinks(listener);
 	passed = passed && checkAgainstCreator(listener);
-	passed = passed && checkAgainstSearchVisibility(listener);
 
 	return passed;
 }
@@ -552,27 +550,6 @@ bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory
 	}
 }
 
-bool LLInventoryFilter::checkAgainstSearchVisibility(const LLFolderViewModelItemInventory* listener) const
-{
-	if (!listener || !hasFilterString()) return TRUE;
-
-	const LLUUID object_id = listener->getUUID();
-	const LLInventoryObject *object = gInventory.getObject(object_id);
-	if (!object) return TRUE;
-
-	const BOOL is_link = object->getIsLinkType();
-	if (is_link && ((mFilterOps.mSearchVisibility & VISIBILITY_LINKS) == 0))
-		return FALSE;
-
-	if (listener->isItemInTrash() && ((mFilterOps.mSearchVisibility & VISIBILITY_TRASH) == 0))
-		return FALSE;
-
-	if (!listener->isAgentInventory() && ((mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY) == 0))
-		return FALSE;
-
-	return TRUE;
-}
-
 const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const
 {
 	return mFilterSubString;
@@ -741,61 +718,6 @@ void LLInventoryFilter::setFilterMarketplaceListingFolders(bool select_only_list
     }
 }
 
-
-void LLInventoryFilter::toggleSearchVisibilityLinks()
-{
-	bool hide_links = mFilterOps.mSearchVisibility & VISIBILITY_LINKS;
-	if (hide_links)
-	{
-		mFilterOps.mSearchVisibility &= ~VISIBILITY_LINKS;
-	}
-	else
-	{
-		mFilterOps.mSearchVisibility |= VISIBILITY_LINKS;
-	}
-
-	if (hasFilterString())
-	{
-		setModified(hide_links ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
-	}
-}
-
-void LLInventoryFilter::toggleSearchVisibilityTrash()
-{
-	bool hide_trash = mFilterOps.mSearchVisibility & VISIBILITY_TRASH;
-	if (hide_trash)
-	{
-		mFilterOps.mSearchVisibility &= ~VISIBILITY_TRASH;
-	}
-	else
-	{
-		mFilterOps.mSearchVisibility |= VISIBILITY_TRASH;
-	}
-
-	if (hasFilterString())
-	{
-		setModified(hide_trash ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
-	}
-}
-
-void LLInventoryFilter::toggleSearchVisibilityLibrary()
-{
-	bool hide_library = mFilterOps.mSearchVisibility & VISIBILITY_LIBRARY;
-	if (hide_library)
-	{
-		mFilterOps.mSearchVisibility &= ~VISIBILITY_LIBRARY;
-	}
-	else
-	{
-		mFilterOps.mSearchVisibility |= VISIBILITY_LIBRARY;
-	}
-
-	if (hasFilterString())
-	{
-		setModified(hide_library ? FILTER_MORE_RESTRICTIVE : FILTER_LESS_RESTRICTIVE);
-	}
-}
-
 void LLInventoryFilter::setFilterNoMarketplaceFolder()
 {
     mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
@@ -1427,11 +1349,6 @@ U64 LLInventoryFilter::getFilterSettingsTypes() const
     return mFilterOps.mFilterSettingsTypes;
 }
 
-U64 LLInventoryFilter::getSearchVisibilityTypes() const
-{
-	return mFilterOps.mSearchVisibility;
-}
-
 bool LLInventoryFilter::hasFilterString() const
 {
 	return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index caba8315c4..be02ee3623 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -99,14 +99,6 @@ public:
 		FILTERCREATOR_OTHERS
 	};
 
-	enum ESearchVisibility
-	{
-		VISIBILITY_NONE = 0,
-		VISIBILITY_TRASH = 0x1 << 0,
-		VISIBILITY_LIBRARY = 0x1 << 1,
-		VISIBILITY_LINKS	= 0x1 << 2
-	};
-
 	struct FilterOps
 	{
 		struct DateRange : public LLInitParam::Block<DateRange>
@@ -162,7 +154,6 @@ public:
 						mFilterWearableTypes,
                         mFilterSettingsTypes, // for _SETTINGS
 						mFilterLinks,
-						mSearchVisibility,
 						mFilterCategoryTypes; // For _CATEGORY
 		LLUUID      	mFilterUUID; 		  // for UUID
 
@@ -202,8 +193,7 @@ public:
 	U64 				getFilterObjectTypes() const;
 	U64					getFilterCategoryTypes() const;
 	U64					getFilterWearableTypes() const;
-	U64					getFilterSettingsTypes() const;
-	U64					getSearchVisibilityTypes() const;
+    U64                 getFilterSettingsTypes() const;
 
 	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const;
 	void 				setFilterObjectTypes(U64 types);
@@ -223,10 +213,6 @@ public:
 	ESearchType			getSearchType() { return mSearchType; }
 	void 				setFilterCreator(EFilterCreatorType type);
 
-	void				toggleSearchVisibilityLinks();
-	void				toggleSearchVisibilityTrash();
-	void				toggleSearchVisibilityLibrary();
-
 	void 				setFilterSubString(const std::string& string);
 	const std::string& 	getFilterSubString(BOOL trim = FALSE) const;
 	const std::string& 	getFilterSubStringOrig() const { return mFilterSubStringOrig; } 
@@ -323,7 +309,6 @@ private:
 	bool 				checkAgainstPermissions(const LLInventoryItem* item) const;
 	bool 				checkAgainstFilterLinks(const class LLFolderViewModelItemInventory* listener) const;
 	bool 				checkAgainstCreator(const class LLFolderViewModelItemInventory* listener) const;
-	bool				checkAgainstSearchVisibility(const class LLFolderViewModelItemInventory* listener) const;
 	bool				checkAgainstClipboard(const LLUUID& object_id) const;
 
 	FilterOps				mFilterOps;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d24440ebbd..02cd22c307 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -115,7 +115,6 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
 	  mSavedFolderState(NULL),
 	  mFilterText(""),
 	  mMenuGearDefault(NULL),
-	  mMenuVisibility(NULL),
 	  mMenuAddHandle(),
 	  mNeedUploadCost(true)
 {
@@ -229,7 +228,6 @@ BOOL LLPanelMainInventory::postBuild()
 	}
 
 	mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
-	mVisibilityMenuButton = getChild<LLMenuButton>("options_visibility_btn");
 
 	initListCommandsHandlers();
 
@@ -1166,9 +1164,6 @@ void LLPanelMainInventory::initListCommandsHandlers()
 	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mMenuAddHandle = menu->getHandle();
 
-	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mVisibilityMenuButton->setMenu(mMenuVisibility);
-
 	// Update the trash button when selected item(s) get worn or taken off.
 	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
 }
@@ -1358,21 +1353,6 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
 		}
 		LLFloaterReg::showInstance("linkreplace", params);
 	}
-
-	if (command_name == "toggle_search_trash")
-	{
-		mActivePanel->getFilter().toggleSearchVisibilityTrash();
-	}
-
-	if (command_name == "toggle_search_library")
-	{
-		mActivePanel->getFilter().toggleSearchVisibilityLibrary();
-	}
-
-	if (command_name == "include_links")
-	{
-		mActivePanel->getFilter().toggleSearchVisibilityLinks();
-	}		
 }
 
 void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility )
@@ -1518,21 +1498,6 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata)
 		return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
 	}
 
-	if (command_name == "toggle_search_trash")
-	{
-		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0;
-	}
-
-	if (command_name == "toggle_search_library")
-	{
-		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0;
-	}
-
-	if (command_name == "include_links")
-	{
-		return (mActivePanel->getFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0;	
-	}	
-
 	return FALSE;
 }
 
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 5211aa0c92..a6bdee233d 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -169,9 +169,7 @@ protected:
 private:
 	LLDragAndDropButton*		mTrashButton;
 	LLToggleableMenu*			mMenuGearDefault;
-	LLToggleableMenu*			mMenuVisibility;
 	LLMenuButton*				mGearMenuButton;
-	LLMenuButton*				mVisibilityMenuButton;
 	LLHandle<LLView>			mMenuAddHandle;
 
 	bool						mNeedUploadCost;
diff --git a/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png b/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png
deleted file mode 100644
index 048da25c92..0000000000
Binary files a/indra/newview/skins/default/textures/icons/Inv_Toolbar_SearchVisibility.png and /dev/null differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 1302edda7a..7325d836d2 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -333,8 +333,6 @@ with the same filename but different name
   <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
   <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
   <texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
-
-  <texture name="Inv_Toolbar_SearchVisibility" file_name="icons/Inv_Toolbar_SearchVisibility.png" preload="false" />
   
   <texture name="Linden_Dollar_Alert" file_name="widgets/Linden_Dollar_Alert.png"/>
   <texture name="Linden_Dollar_Background" file_name="widgets/Linden_Dollar_Background.png"/>
@@ -650,7 +648,6 @@ with the same filename but different name
   <texture name="TextField_Search_Off" file_name="widgets/TextField_Search_Off.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Disabled" file_name="widgets/TextField_Disabled.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
   <texture name="TextField_Active" file_name="widgets/TextField_Active.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
-  <texture name="TextField_Search_Highlight" file_name="widgets/TextField_Search_Highlight.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
 
 
   <texture name="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
diff --git a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png b/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png
deleted file mode 100644
index e3944289c6..0000000000
Binary files a/indra/newview/skins/default/textures/widgets/TextField_Search_Highlight.png and /dev/null differ
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml b/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
deleted file mode 100644
index 46193f4a7a..0000000000
--- a/indra/newview/skins/default/xui/en/menu_inventory_search_visibility.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<toggleable_menu
- bottom="806"
- layout="topleft"
- left="0"
- mouse_opaque="false"
- name="menu_search_visibility"
- visible="false">
-  <menu_item_check
-   label="Search Trash"
-   layout="topleft"
-   name="search_trash">
-    <on_click
-     function="Inventory.GearDefault.Custom.Action"
-     parameter="toggle_search_trash" />
-    <on_check
-     function="Inventory.GearDefault.Check"
-     parameter="toggle_search_trash" />
-  </menu_item_check>
-  <menu_item_check
-   label="Search Library"
-   layout="topleft"
-   name="search_library">
-    <on_click
-     function="Inventory.GearDefault.Custom.Action"
-     parameter="toggle_search_library" />
-    <on_check
-     function="Inventory.GearDefault.Check"
-     parameter="toggle_search_library" />
-  </menu_item_check>
-  <menu_item_separator
-   layout="topleft" />
-  <menu_item_check
-   label="Include links"
-   layout="topleft"
-   name="include_links">
-    <on_click
-     function="Inventory.GearDefault.Custom.Action"
-     parameter="include_links" />
-    <on_check
-     function="Inventory.GearDefault.Check"
-     parameter="include_links" />         
-  </menu_item_check>    
-</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index 2ff58035ed..d77fbdec0a 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -32,20 +32,30 @@
     		 left="12"
 		     name="ItemcountText"
 		     font="SansSerifMedium"
-		     text_color="InventoryItemLinkColor"
+		     text_color="EmphasisColor"
 		     use_ellipses="true"
 		     top_pad="0"
 		     width="300">
     Items:
   </text>
-  <combo_box
+  <filter_editor
+   text_pad_left="10"
+   follows="left|top|right"
    height="23"
+   label="Enter search text"
    layout="topleft"
    left="10"
+   max_length_chars="300"
+   name="inventory search editor"
    top="18"
+   width="208" />
+  <combo_box
+   height="23"
+   layout="topleft"
+   left_pad="4"
    name="search_type"
-   follows="top|left"
-   width="88">
+   follows="top|right"
+   width="90">
     <item
      label="Name"
      name="Name"
@@ -62,27 +72,7 @@
      label="UUID"
      name="UUID"
      value="search_by_UUID"/>
-  </combo_box>
-  <menu_button
-   follows="top|left"
-   tool_tip="Show search visibility options"
-   height="23"
-   image_overlay="Inv_Toolbar_SearchVisibility"
-   layout="topleft"
-   left_pad="3"
-   name="options_visibility_btn"
-   width="31" />
-  <filter_editor
-   text_pad_left="10"
-   follows="left|top|right"
-   height="23"
-   label="Enter search text"
-   layout="topleft"
-   left_pad="3"
-   max_length_chars="300"
-   highlight_text_field="true"
-   name="inventory search editor"
-   width="177" />
+    </combo_box>
   <tab_container
      follows="all"
      halign="center"
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index 1c4822b8d5..2cc4abdd30 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -6,11 +6,9 @@
   text_pad_left="7"
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
-  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active"
-  background_image_highlight="TextField_Search_Highlight">
+  background_image_focused="TextField_Search_Active">
   <search_button label=""
     top_pad="4"
     left_pad="4"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index dc5a07bf4f..faa0404b35 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,11 +7,9 @@
   text_pad_right="6" 
   select_on_focus="true"
   text_tentative_color="TextFgTentativeColor"
-  highlight_text_field="false"
   background_image="TextField_Search_Off"
   background_image_disabled="TextField_Search_Disabled"
-  background_image_focused="TextField_Search_Active"
-  background_image_highlight="TextField_Search_Highlight">
+  background_image_focused="TextField_Search_Active" >
   <search_button 
     top_pad="4"
     left_pad="4" 
-- 
cgit v1.2.3


From baf77b4dd01d036b77d635c19c7113bcac2dc6ec Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:31:18 +0300
Subject: Revert "SL-13824 Remove notification when both joining a group and
 leaving a group"

This reverts commit 34786ac22129aac372eeb1e73b6baac6bfad644e.
---
 indra/newview/llviewermessage.cpp                    | 9 ---------
 indra/newview/skins/default/xui/en/notifications.xml | 7 +++++++
 2 files changed, 7 insertions(+), 9 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9c56766d0d..e78ace061e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -5036,15 +5036,6 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
 		// notification was specified using the new mechanism, so we can just handle it here
 		std::string notificationID;
 		msgsystem->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, notificationID);
-
-		//SL-13824 skip notification when both joining a group and leaving a group
-		//remove this after server stops sending these messages  
-		if (notificationID == "JoinGroupSuccess" ||
-			notificationID == "GroupDepart")
-		{
-			return true;
-		}
-
 		if (!LLNotifications::getInstance()->templateExists(notificationID))
 		{
 			return false;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index d141cfc313..fa1c15c411 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4214,6 +4214,13 @@ Leave Group?
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="GroupDepart"
+   type="notify">
+You have left the group &apos;&lt;nolink&gt;[group_name]&lt;/nolink&gt;&apos;.
+    <tag>group</tag>
+  </notification>
 
   <notification
    icon="alertmodal.tga"
-- 
cgit v1.2.3


From be233707e1a0a4246be8fabe17419476deec8949 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:31:25 +0300
Subject: Revert "SL-13824 Remove notification when joining a group"

This reverts commit fc74a2df6364889149b5ebd0638839582fda358f.
---
 indra/newview/llviewermessage.cpp                    |  1 +
 indra/newview/skins/default/xui/en/notifications.xml | 12 ++++++++++++
 2 files changed, 13 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e78ace061e..06a8ebbe89 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -777,6 +777,7 @@ void response_group_invitation_coro(std::string url, LLUUID group_id, bool notif
             LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL;
             if (notify_and_update)
             {
+                LLNotificationsUtil::add("JoinGroupSuccess");
                 gAgent.sendAgentDataUpdateRequest();
 
                 LLGroupMgr::getInstance()->clearGroupData(group_id);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index fa1c15c411..32ae56e3af 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -1022,6 +1022,18 @@ The group no longer has open enrollment.
        yestext="OK"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="JoinGroupSuccess"
+   type="alertmodal">
+You have been added to the group
+    <tag>group_id</tag>
+    <tag>success</tag>
+    <usetemplate
+       name="okbutton"
+       yestext="OK"/>
+  </notification>
+  
   <notification
    icon="alertmodal.tga"
    name="JoinGroupInsufficientFunds"
-- 
cgit v1.2.3


From 8b410efa4f6eccb689f6adb901ec3eec8cdd8541 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 23 Sep 2020 12:31:47 +0300
Subject: Revert " SL-13823  FIXED "Settings" are not shown in Inventory filter
 message"

This reverts commit 0048a4cf18f958591c5e4f9ec829e4ecdc642926.
---
 indra/newview/llinventoryfilter.cpp            | 12 ------------
 indra/newview/skins/default/xui/en/strings.xml |  1 -
 2 files changed, 13 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 8f18de0210..745b953996 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -1230,18 +1230,6 @@ const std::string& LLInventoryFilter::getFilterText()
 		filtered_by_all_types = FALSE;
 	}
 
-	if (isFilterObjectTypesWith(LLInventoryType::IT_SETTINGS))
-	{
-		filtered_types +=  LLTrans::getString("Settings");
-		filtered_by_type = TRUE;
-		num_filter_types++;
-	}
-	else
-	{
-		not_filtered_types +=  LLTrans::getString("Settings");
-		filtered_by_all_types = FALSE;
-	}
-
 	if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
 		&& filtered_by_type
 		&& !filtered_by_all_types)
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c9ea423a20..1bfac6aeb7 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2415,7 +2415,6 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="Scripts"       value=" Scripts," />
 	<string name="Sounds"        value=" Sounds," />
 	<string name="Textures"      value=" Textures," />
-	<string name="Settings"      value=" Settings," />
 	<string name="Snapshots"     value=" Snapshots," />
 	<string name="No Filters"    value="No " />
 	<string name="Since Logoff"  value=" - Since Logoff" />
-- 
cgit v1.2.3


From bf8cc6b2f7d0563a61dcc45b7feaf4fffacbfbe1 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 23 Sep 2020 22:44:17 +0300
Subject: SL-13986 Validate buffer size to avoid SIGBUS crash on sscanf

---
 indra/llinventory/lllandmark.cpp | 142 +++++++++++++++++++++++++--------------
 indra/llinventory/lllandmark.h   |   2 +-
 indra/newview/lllandmarklist.cpp |  63 ++++++++---------
 3 files changed, 125 insertions(+), 82 deletions(-)

(limited to 'indra')

diff --git a/indra/llinventory/lllandmark.cpp b/indra/llinventory/lllandmark.cpp
index 4c6075d6b5..789716b449 100644
--- a/indra/llinventory/lllandmark.cpp
+++ b/indra/llinventory/lllandmark.cpp
@@ -103,60 +103,100 @@ LLVector3 LLLandmark::getRegionPos() const
 
 
 // static
-LLLandmark* LLLandmark::constructFromString(const char *buffer)
+LLLandmark* LLLandmark::constructFromString(const char *buffer, const S32 buffer_size)
 {
-	const char* cur = buffer;
 	S32 chars_read = 0;
+	S32 chars_read_total = 0;
 	S32 count = 0;
 	U32 version = 0;
 
+    bool bad_block = false;
+    LLLandmark* result = NULL;
+
 	// read version 
-	count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read );
-	if(count != 1)
-	{
-		goto error;
-	}
+	count = sscanf( buffer, "Landmark version %u\n%n", &version, &chars_read );
 
-	if(version == 1)
-	{
-		LLVector3d pos;
-		cur += chars_read;
-		// read position
-		count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read );
-		if( count != 3 )
-		{
-			goto error;
-		}
-		cur += chars_read;
-		// LL_INFOS() << "Landmark read: " << pos << LL_ENDL;
-		
-		return new LLLandmark(pos);
-	}
-	else if(version == 2)
-	{
-		// *NOTE: Changing the buffer size will require changing the
-		// scanf call below.
-		char region_id_str[MAX_STRING];	/* Flawfinder: ignore */
-		LLVector3 pos;
-		cur += chars_read;
-		count = sscanf(	/* Flawfinder: ignore */
-			cur,
-			"region_id %254s\n%n",
-			region_id_str, &chars_read);
-		if(count != 1) goto error;
-		cur += chars_read;
-		count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read);
-		if(count != 3) goto error;
-		cur += chars_read;
-		LLLandmark* lm = new LLLandmark;
-		lm->mRegionID.set(region_id_str);
-		lm->mRegionPos = pos;
-		return lm;
-	}
+    if (count != 1)
+    {
+        bad_block = true;
+    }
+
+    chars_read_total += chars_read;
+
+    if (chars_read_total >= buffer_size)
+    {
+        // either file was truncated or data in file was damaged
+        bad_block = true;
+    }
+
+    if (!bad_block)
+    {
+        switch (version)
+        {
+            case 1:
+            {
+                LLVector3d pos;
+                // read position
+                count = sscanf(buffer + chars_read_total, "position %lf %lf %lf\n%n", pos.mdV + VX, pos.mdV + VY, pos.mdV + VZ, &chars_read);
+                if (count != 3)
+                {
+                    bad_block = true;
+                }
+                else
+                {
+                    LL_DEBUGS("Landmark") << "Landmark read: " << pos << LL_ENDL;
+                    result = new LLLandmark(pos);
+                }
+                break;
+            }
+            case 2:
+            {
+                // *NOTE: Changing the buffer size will require changing the
+                // scanf call below.
+                char region_id_str[MAX_STRING];
+                LLVector3 pos;
+                count = sscanf( buffer + chars_read_total,
+                                "region_id %254s\n%n",
+                                region_id_str,
+                                &chars_read);
+                if (count != 1)
+                {
+                    bad_block = true;
+                }
+                chars_read_total += chars_read;
+                if (chars_read_total >= buffer_size)
+                {
+                    bad_block = true;
+                }
+                if (!bad_block)
+                {
+                    count = sscanf(buffer + chars_read_total, "local_pos %f %f %f\n%n", pos.mV + VX, pos.mV + VY, pos.mV + VZ, &chars_read);
+                    if (count != 3)
+                    {
+                        bad_block = true;
+                    }
+                    else
+                    {
+                        result = new LLLandmark;
+                        result->mRegionID.set(region_id_str);
+                        result->mRegionPos = pos;
+                    }
+                }
+                break;
+            }
+            default:
+            {
+                LL_INFOS("Landmark") << "Encountered Unknown landmark version " << version << LL_ENDL;
+                break;
+            }
+        }
+    }
 
- error:
-	LL_INFOS() << "Bad Landmark Asset: bad _DATA_ block." << LL_ENDL;
-	return NULL;
+    if (bad_block)
+    {
+        LL_INFOS("Landmark") << "Bad Landmark Asset: bad _DATA_ block." << LL_ENDL;
+    }
+    return result;
 }
 
 
@@ -176,7 +216,7 @@ void LLLandmark::requestRegionHandle(
 	if(region_id.isNull())
 	{
 		// don't bother with checking - it's 0.
-		LL_DEBUGS() << "requestRegionHandle: null" << LL_ENDL;
+		LL_DEBUGS("Landmark") << "requestRegionHandle: null" << LL_ENDL;
 		if(callback)
 		{
 			const U64 U64_ZERO = 0;
@@ -187,7 +227,7 @@ void LLLandmark::requestRegionHandle(
 	{
 		if(region_id == mLocalRegion.first)
 		{
-			LL_DEBUGS() << "requestRegionHandle: local" << LL_ENDL;
+			LL_DEBUGS("Landmark") << "requestRegionHandle: local" << LL_ENDL;
 			if(callback)
 			{
 				callback(region_id, mLocalRegion.second);
@@ -198,13 +238,13 @@ void LLLandmark::requestRegionHandle(
 			region_map_t::iterator it = mRegions.find(region_id);
 			if(it == mRegions.end())
 			{
-				LL_DEBUGS() << "requestRegionHandle: upstream" << LL_ENDL;
+				LL_DEBUGS("Landmark") << "requestRegionHandle: upstream" << LL_ENDL;
 				if(callback)
 				{
 					region_callback_map_t::value_type vt(region_id, callback);
 					sRegionCallbackMap.insert(vt);
 				}
-				LL_DEBUGS() << "Landmark requesting information about: "
+				LL_DEBUGS("Landmark") << "Landmark requesting information about: "
 						 << region_id << LL_ENDL;
 				msg->newMessage("RegionHandleRequest");
 				msg->nextBlock("RequestBlock");
@@ -214,7 +254,7 @@ void LLLandmark::requestRegionHandle(
 			else if(callback)
 			{
 				// we have the answer locally - just call the callack.
-				LL_DEBUGS() << "requestRegionHandle: ready" << LL_ENDL;
+				LL_DEBUGS("Landmark") << "requestRegionHandle: ready" << LL_ENDL;
 				callback(region_id, (*it).second.mRegionHandle);
 			}
 		}
diff --git a/indra/llinventory/lllandmark.h b/indra/llinventory/lllandmark.h
index 92923ea6fb..be34113a90 100644
--- a/indra/llinventory/lllandmark.h
+++ b/indra/llinventory/lllandmark.h
@@ -60,7 +60,7 @@ public:
 
 	// constructs a new LLLandmark from a string
 	// return NULL if there's an error
-	static LLLandmark* constructFromString(const char *buffer);
+	static LLLandmark* constructFromString(const char *buffer, const S32 buffer_size);
 
 	// register callbacks that this class handles
 	static void registerCallbacks(LLMessageSystem* msg);
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index c58540914e..a790e513a2 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -109,36 +109,39 @@ void LLLandmarkList::processGetAssetReply(
 		LLVFile file(vfs, uuid, type);
 		S32 file_length = file.getSize();
 
-		std::vector<char> buffer(file_length + 1);
-		file.read( (U8*)&buffer[0], file_length);
-		buffer[ file_length ] = 0;
-
-		LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0]);
-		if (landmark)
-		{
-			gLandmarkList.mList[ uuid ] = landmark;
-			gLandmarkList.mRequestedList.erase(uuid);
-			
-			LLVector3d pos;
-			if(!landmark->getGlobalPos(pos))
-			{
-				LLUUID region_id;
-				if(landmark->getRegionID(region_id))
-				{
-					LLLandmark::requestRegionHandle(
-						gMessageSystem,
-						gAgent.getRegionHost(),
-						region_id,
-						boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid));
-				}
-
-				// the callback will be called when we get the region handle.
-			}
-			else
-			{
-				gLandmarkList.makeCallbacks(uuid);
-			}
-		}
+        if (file_length > 0)
+        {
+            std::vector<char> buffer(file_length + 1);
+            file.read((U8*)&buffer[0], file_length);
+            buffer[file_length] = 0;
+
+            LLLandmark* landmark = LLLandmark::constructFromString(&buffer[0], buffer.size());
+            if (landmark)
+            {
+                gLandmarkList.mList[uuid] = landmark;
+                gLandmarkList.mRequestedList.erase(uuid);
+
+                LLVector3d pos;
+                if (!landmark->getGlobalPos(pos))
+                {
+                    LLUUID region_id;
+                    if (landmark->getRegionID(region_id))
+                    {
+                        LLLandmark::requestRegionHandle(
+                            gMessageSystem,
+                            gAgent.getRegionHost(),
+                            region_id,
+                            boost::bind(&LLLandmarkList::onRegionHandle, &gLandmarkList, uuid));
+                    }
+
+                    // the callback will be called when we get the region handle.
+                }
+                else
+                {
+                    gLandmarkList.makeCallbacks(uuid);
+                }
+            }
+        }
 	}
 	else
 	{
-- 
cgit v1.2.3


From 94ebf52edd6d1a610bf4cbfcc304dda21d544951 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 24 Sep 2020 20:56:23 +0300
Subject: SL-12435 Crash on mRowPanels.back()

---
 indra/newview/lloutfitgallery.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 3d1428bb63..fd01be6531 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -67,6 +67,7 @@ LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)
       mOutfitsObserver(NULL),
       mScrollPanel(NULL),
       mGalleryPanel(NULL),
+      mLastRowPanel(NULL),
       mGalleryCreated(false),
       mRowCount(0),
       mItemsAddedCount(0),
@@ -239,7 +240,15 @@ void LLOutfitGallery::removeLastRow()
     mGalleryPanel->removeChild(mLastRowPanel);
     mUnusedRowPanels.push_back(mLastRowPanel);
     mRowPanels.pop_back();
-    mLastRowPanel = mRowPanels.back();
+    if (mRowPanels.size() > 0)
+    {
+        // Just removed last row
+        mLastRowPanel = mRowPanels.back();
+    }
+    else
+    {
+        mLastRowPanel = NULL;
+    }
 }
 
 LLPanel* LLOutfitGallery::addToRow(LLPanel* row_stack, LLOutfitGalleryItem* item, int pos, int hgap)
-- 
cgit v1.2.3


From 652e8459001e052edd6eeef0b919d4d68c8daa58 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 24 Sep 2020 21:09:38 +0300
Subject: SL-13986 Validate uuid

---
 indra/llinventory/lllandmark.cpp | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

(limited to 'indra')

diff --git a/indra/llinventory/lllandmark.cpp b/indra/llinventory/lllandmark.cpp
index 789716b449..bd7ab3c2c8 100644
--- a/indra/llinventory/lllandmark.cpp
+++ b/indra/llinventory/lllandmark.cpp
@@ -115,17 +115,11 @@ LLLandmark* LLLandmark::constructFromString(const char *buffer, const S32 buffer
 
 	// read version 
 	count = sscanf( buffer, "Landmark version %u\n%n", &version, &chars_read );
-
-    if (count != 1)
-    {
-        bad_block = true;
-    }
-
     chars_read_total += chars_read;
 
-    if (chars_read_total >= buffer_size)
+    if (count != 1
+        || chars_read_total >= buffer_size)
     {
-        // either file was truncated or data in file was damaged
         bad_block = true;
     }
 
@@ -155,19 +149,29 @@ LLLandmark* LLLandmark::constructFromString(const char *buffer, const S32 buffer
                 // scanf call below.
                 char region_id_str[MAX_STRING];
                 LLVector3 pos;
+                LLUUID region_id;
                 count = sscanf( buffer + chars_read_total,
                                 "region_id %254s\n%n",
                                 region_id_str,
                                 &chars_read);
-                if (count != 1)
+                chars_read_total += chars_read;
+
+                if (count != 1
+                    || chars_read_total >= buffer_size
+                    || !LLUUID::validate(region_id_str))
                 {
                     bad_block = true;
                 }
-                chars_read_total += chars_read;
-                if (chars_read_total >= buffer_size)
+
+                if (!bad_block)
                 {
-                    bad_block = true;
+                    region_id.set(region_id_str);
+                    if (region_id.isNull())
+                    {
+                        bad_block = true;
+                    }
                 }
+
                 if (!bad_block)
                 {
                     count = sscanf(buffer + chars_read_total, "local_pos %f %f %f\n%n", pos.mV + VX, pos.mV + VY, pos.mV + VZ, &chars_read);
@@ -178,7 +182,7 @@ LLLandmark* LLLandmark::constructFromString(const char *buffer, const S32 buffer
                     else
                     {
                         result = new LLLandmark;
-                        result->mRegionID.set(region_id_str);
+                        result->mRegionID = region_id;
                         result->mRegionPos = pos;
                     }
                 }
-- 
cgit v1.2.3


From 56e427d0eb12f5f89ffde27a2cb5026fd5c0589c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 28 Sep 2020 19:54:00 +0000
Subject: SL-13995 User Friendly Script Name In External Editor Tab

---
 indra/newview/llpreviewscript.cpp | 52 +++++++++++++++++++++++++++++----------
 indra/newview/llpreviewscript.h   |  2 +-
 2 files changed, 40 insertions(+), 14 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 7a68d1e270..8bd67c987c 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -639,14 +639,17 @@ bool LLScriptEdCore::writeToFile(const std::string& filename)
 
 void LLScriptEdCore::sync()
 {
-	// Sync with external editor.
-	std::string tmp_file = mContainer->getTmpFileName();
-	llstat s;
-	if (LLFile::stat(tmp_file, &s) == 0) // file exists
-	{
-		if (mLiveFile) mLiveFile->ignoreNextUpdate();
-		writeToFile(tmp_file);
-	}
+    // Sync with external editor.
+    if (mLiveFile)
+    {
+        std::string tmp_file = mLiveFile->filename();
+        llstat s;
+        if (LLFile::stat(tmp_file, &s) == 0) // file exists
+        {
+            mLiveFile->ignoreNextUpdate();
+            writeToFile(tmp_file);
+        }
+    }
 }
 
 bool LLScriptEdCore::hasChanged()
@@ -1032,9 +1035,25 @@ void LLScriptEdCore::openInExternalEditor()
 {
 	delete mLiveFile; // deletes file
 
-	// Save the script to a temporary file.
-	std::string filename = mContainer->getTmpFileName();
-	writeToFile(filename);
+	// Generate a suitable filename
+    std::string script_name = mScriptName;
+    std::string forbidden_chars = "<>:\"\\/|?*";
+    for (std::string::iterator c = forbidden_chars.begin(); c != forbidden_chars.end(); c++)
+    {
+        script_name.erase(std::remove(script_name.begin(), script_name.end(), *c), script_name.end());
+    }
+	std::string filename = mContainer->getTmpFileName(script_name);
+
+    // Save the script to a temporary file.
+    if (!writeToFile(filename))
+    {
+        // In case some characters from script name are forbidden
+        // and not accounted for, name is too long or some other issue,
+        // try file that doesn't include script name
+        script_name.clear();
+        filename = mContainer->getTmpFileName(script_name);
+        writeToFile(filename);
+    }
 
 	// Start watching file changes.
 	mLiveFile = new LLLiveLSLFile(filename, boost::bind(&LLScriptEdContainer::onExternalChange, mContainer, _1));
@@ -1424,7 +1443,7 @@ LLScriptEdContainer::LLScriptEdContainer(const LLSD& key) :
 {
 }
 
-std::string LLScriptEdContainer::getTmpFileName()
+std::string LLScriptEdContainer::getTmpFileName(const std::string& script_name)
 {
 	// Take script inventory item id (within the object inventory)
 	// to consideration so that it's possible to edit multiple scripts
@@ -1436,7 +1455,14 @@ std::string LLScriptEdContainer::getTmpFileName()
 	LLMD5 script_id_hash((const U8 *)script_id.c_str());
 	script_id_hash.hex_digest(script_id_hash_str);
 
-	return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl";
+    if (script_name.empty())
+    {
+        return std::string(LLFile::tmpdir()) + "sl_script_" + script_id_hash_str + ".lsl";
+    }
+    else
+    {
+        return std::string(LLFile::tmpdir()) + "sl_script_" + script_name + "_" + script_id_hash_str + ".lsl";
+    }
 }
 
 bool LLScriptEdContainer::onExternalChange(const std::string& filename)
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index 74e4c00d43..612789e4b5 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -206,7 +206,7 @@ public:
 	LLScriptEdContainer(const LLSD& key, const bool live);
 
 protected:
-	std::string		getTmpFileName();
+	std::string		getTmpFileName(const std::string& script_name);
 	bool			onExternalChange(const std::string& filename);
 	virtual void	saveIfNeeded(bool sync = true) = 0;
 
-- 
cgit v1.2.3


From 508f4ead593b5d950edb3707e530cdef4603a8b5 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 29 Sep 2020 19:37:19 +0300
Subject: SL-13990 'My last location' sometimes is not applied

---
 indra/newview/llpanellogin.cpp | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index da21d5e69a..2d501b5783 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -458,6 +458,9 @@ void LLPanelLogin::addFavoritesToStartLocation()
 	if (combo->getValue().asString().empty())
 	{
 		combo->selectFirstItem();
+        // Value 'home' or 'last' should have been taken from NextLoginLocation
+        // but NextLoginLocation was not set, so init it from combo explicitly
+        onLocationSLURL();
 	}
 }
 
@@ -1340,6 +1343,7 @@ void LLPanelLogin::onSelectServer()
 			{
 				// the grid specified by the location is not this one, so clear the combo
 				location_combo->setCurrentByIndex(0); // last location on the new grid
+				onLocationSLURL();
 			}
 		}			
 		break;
-- 
cgit v1.2.3


From 0b395f01f9cfc71bdc6692c4392ffe3da50963ee Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 30 Sep 2020 14:25:21 +0300
Subject: SL-13570 FIXED The name of the item is overlapped by search term in
 inventory

---
 indra/llui/llfolderviewitem.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 9a1f7de73b..177684c5e3 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -914,9 +914,10 @@ void LLFolderViewItem::draw()
 	//
     if (filter_string_length > 0)
     {
-        F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mViewModelItem->getFilterStringOffset());
+        S32 filter_offset = mViewModelItem->getFilterStringOffset();
+        F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, filter_offset + filter_string_length) - font->getWidthF32(combined_string, filter_offset, filter_string_length);
         F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)mTextPad - (F32)TOP_PAD;
-        font->renderUTF8( combined_string, mViewModelItem->getFilterStringOffset(), match_string_left, yy,
+        font->renderUTF8( combined_string, filter_offset, match_string_left, yy,
             sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
             filter_string_length, S32_MAX, &right_x, FALSE );
     }
-- 
cgit v1.2.3


From f9d90dbf3dffb56fdcfe979ed1921ae3add04d45 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 1 Oct 2020 18:07:55 +0300
Subject: SL-14027 Save asset to Settings folder instead of Library

---
 indra/newview/llfloaterfixedenvironment.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 37e162b249..5ce217fb33 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -496,7 +496,8 @@ void LLFloaterFixedEnvironment::onSaveAsCommit(const LLSD& notification, const L
         {
             const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
             LLUUID parent_id = mInventoryItem->getParentUUID();
-            if (marketplacelistings_id == parent_id)
+            
+            if ((marketplacelistings_id == parent_id) || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
             {
                 parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
             }
-- 
cgit v1.2.3


From 071e0ff36b510f66100ca338c8ef923858d8c451 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Mon, 4 Jan 2021 17:29:50 +0200
Subject: SL-14494 FIXED llRequestURL() generated URLs are no longer recognized
 by the viewer as Second Life hosted URLs

---
 indra/llui/llurlentry.cpp | 4 +++-
 indra/newview/llweb.cpp   | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 5be15eac13..55b33396f7 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -464,7 +464,9 @@ LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
 							"|"
 							"(https://([-\\w\\.]*\\.)?(secondlife|lindenlab|tilia-inc)\\.com(:\\d{1,5})?)"
 							"|"
-							"(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?))"
+							"(https://([-\\w\\.]*\\.)?secondlifegrid\\.net(:\\d{1,5})?)"
+							"|"
+							"(https?://([-\\w\\.]*\\.)?secondlife\\.io(:\\d{1,5})?))"
 							"\\/\\S*",
 		boost::regex::perl|boost::regex::icase);
 	
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 63257d6543..d019b400e8 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -237,7 +237,7 @@ bool LLWeb::useExternalBrowser(const std::string &url)
 		up.extractParts();
 		std::string uri_string = up.host();
 
-		boost::regex pattern = boost::regex("\\b(lindenlab.com|secondlife.com)$", boost::regex::perl|boost::regex::icase);
+		boost::regex pattern = boost::regex("\\b(lindenlab.com|secondlife.com|secondlife.io)$", boost::regex::perl|boost::regex::icase);
 		boost::match_results<std::string::const_iterator> matches;
 		return !(boost::regex_search(uri_string, matches, pattern));
 	}
-- 
cgit v1.2.3


From fff8ab23a82c4a0c644d7bf6b5d1ddcdb875b361 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 9 Feb 2021 17:33:19 +0200
Subject: SL-14675 Teleporting to a new region can load the wrong EEP
 environment layer

---
 indra/newview/llenvironment.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index f0614487c4..d828bbf59b 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1756,8 +1756,11 @@ void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentI
         }
         else
         {
-            setEnvironment(ENV_REGION, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);
             mTrackAltitudes = envinfo->mAltitudes;
+            // update track selection based on new altitudes
+            mCurrentTrack = calculateSkyTrackForAltitude(gAgent.getPositionAgent().mV[VZ]);
+
+            setEnvironment(ENV_REGION, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);
         }
 
         LL_DEBUGS("ENVIRONMENT") << "Altitudes set to {" << mTrackAltitudes[0] << ", "<< mTrackAltitudes[1] << ", " << mTrackAltitudes[2] << ", " << mTrackAltitudes[3] << LL_ENDL;
-- 
cgit v1.2.3


From 199f82786e1a19af519afa4713d2cced44c640d8 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 9 Feb 2021 19:02:22 +0200
Subject: SL-14675 Position changes shouldn't cause additional blends when
 environment isn't ready

---
 indra/newview/llenvironment.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index d828bbf59b..b6f120e644 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -2380,6 +2380,15 @@ void LLEnvironment::onAgentPositionHasChanged(const LLVector3 &localpos)
         return;
 
     mCurrentTrack = trackno;
+
+    LLViewerRegion* cur_region = gAgent.getRegion();
+    if (!cur_region || !cur_region->capabilitiesReceived())
+    {
+        // Environment not ready, environment will be updated later, don't cause 'blend' yet.
+        // But keep mCurrentTrack updated in case we won't get new altitudes for some reason
+        return;
+    }
+
     for (S32 env = ENV_LOCAL; env < ENV_DEFAULT; ++env)
     {
         if (mEnvironments[env])
-- 
cgit v1.2.3


From 24d4517458f46ad0cd7284a5f30c4d961d518aa8 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 10 Feb 2021 01:10:36 +0200
Subject: SL-14807 Viewer crashes when creating an experience

---
 indra/llmessage/llcoproceduremanager.cpp | 18 ++++++++++++------
 indra/llmessage/llcoproceduremanager.h   |  4 ++--
 indra/llmessage/llexperiencecache.cpp    |  2 ++
 indra/newview/llstartup.cpp              |  3 ---
 indra/newview/llviewerassetstorage.cpp   |  1 +
 5 files changed, 17 insertions(+), 11 deletions(-)

(limited to 'indra')

diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index a4fe3a2a8e..850d4da74f 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -138,7 +138,7 @@ LLCoprocedureManager::~LLCoprocedureManager()
     close();
 }
 
-LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName)
+void LLCoprocedureManager::initializePool(const std::string &poolName)
 {
     // Attempt to look up a pool size in the configuration.  If found use that
     std::string keyName = "PoolSize" + poolName;
@@ -171,8 +171,6 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::
 
     bool inserted = mPoolMap.emplace(poolName, pool).second;
     LL_ERRS_IF(!inserted, "CoprocedureManager") << "Unable to add pool named \"" << poolName << "\" to map. FATAL!" << LL_ENDL;
-
-    return pool;
 }
 
 //-------------------------------------------------------------------------
@@ -182,20 +180,28 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s
     // not exist, create it.
     poolMap_t::iterator it = mPoolMap.find(pool);
 
-    poolPtr_t targetPool = (it != mPoolMap.end()) ? it->second : initializePool(pool);
+    if (it == mPoolMap.end())
+    {
+        // initializing pools in enqueueCoprocedure is not thread safe,
+        // at the moment pools need to be initialized manually
+        LL_ERRS() << "Uninitialized pool " << name << LL_ENDL;
+    }
 
+    poolPtr_t targetPool = it->second;
     return targetPool->enqueueCoprocedure(name, proc);
 }
 
 void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn)
 {
     // functions to discover and store the pool sizes
+    // Might be a better idea to make an initializePool(name, size) to init everything externally
     mPropertyQueryFn = queryfn;
     mPropertyDefineFn = updatefn;
 
-    // workaround until we get mutex into initializePool
-    initializePool("VAssetStorage");
     initializePool("Upload");
+    initializePool("AIS"); // it might be better to have some kind of on-demand initialization for AIS
+    // "ExpCache" pool gets initialized in LLExperienceCache
+    // asset storage pool gets initialized in LLViewerAssetStorage
 }
 
 //-------------------------------------------------------------------------
diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h
index 70204ba02b..d6973996a9 100644
--- a/indra/llmessage/llcoproceduremanager.h
+++ b/indra/llmessage/llcoproceduremanager.h
@@ -79,6 +79,8 @@ public:
 
     void close();
     void close(const std::string &pool);
+
+    void initializePool(const std::string &poolName);
     
 private:
 
@@ -87,8 +89,6 @@ private:
 
     poolMap_t mPoolMap;
 
-    poolPtr_t initializePool(const std::string &poolName);
-
     SettingQuery_t mPropertyQueryFn;
     SettingUpdate_t mPropertyDefineFn;
 };
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index 64c01bd9eb..db22ad2ea3 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -108,6 +108,8 @@ void LLExperienceCache::initSingleton()
         cache_stream >> (*this);
     }
 
+    LLCoprocedureManager::instance().initializePool("ExpCache");
+
     LLCoros::instance().launch("LLExperienceCache::idleCoro",
         boost::bind(&LLExperienceCache::idleCoro, this));
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 17777c3ceb..e4a5687dc6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1818,9 +1818,6 @@ bool idle_startup()
 		
 		display_startup();
 
-		//all categories loaded. lets create "My Favorites" category
-		gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
-
 		// set up callbacks
 		LL_INFOS() << "Registering Callbacks" << LL_ENDL;
 		LLMessageSystem* msg = gMessageSystem;
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 54f80a2995..b345396c2f 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -128,6 +128,7 @@ LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *
       mCountSucceeded(0),
       mTotalBytesFetched(0)
 {
+    LLCoprocedureManager::instance().initializePool(VIEWER_ASSET_STORAGE_CORO_POOL);
 }
 
 LLViewerAssetStorage::~LLViewerAssetStorage()
-- 
cgit v1.2.3


From 661d59596723e519466e7a5ce3d9742bcc544211 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Wed, 10 Feb 2021 13:39:10 +0200
Subject: SL-13497 Fixed error in logic

---
 indra/llplugin/llpluginprocessparent.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 7d18bae947..e5b4dec1bd 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -154,9 +154,9 @@ void LLPluginProcessParent::shutdown()
     {
         EState state = (*it).second->mState;
         if (state != STATE_CLEANUP
-            || state != STATE_EXITING
-            || state != STATE_DONE
-            || state != STATE_ERROR)
+            && state != STATE_EXITING
+            && state != STATE_DONE
+            && state != STATE_ERROR)
         {
             (*it).second->setState(STATE_GOODBYE);
         }
-- 
cgit v1.2.3


From 4a3e32e732e5fce6ecc02c15ef8966363f5a8f76 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 11 Feb 2021 02:49:13 +0200
Subject: SL-14807 Adjusted unit test

---
 indra/llmessage/llcoproceduremanager.cpp            | 2 +-
 indra/llmessage/tests/llcoproceduremanager_test.cpp | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index 850d4da74f..c50d2bfd41 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -184,7 +184,7 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s
     {
         // initializing pools in enqueueCoprocedure is not thread safe,
         // at the moment pools need to be initialized manually
-        LL_ERRS() << "Uninitialized pool " << name << LL_ENDL;
+        LL_ERRS() << "Uninitialized pool " << pool << LL_ENDL;
     }
 
     poolPtr_t targetPool = it->second;
diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp
index 9db13a37b5..6424117ef3 100644
--- a/indra/llmessage/tests/llcoproceduremanager_test.cpp
+++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp
@@ -91,6 +91,7 @@ namespace tut
     {
         Sync sync;
         int foo = 0;
+        LLCoprocedureManager::instance().initializePool("PoolName");
         LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",
             [&foo, &sync] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t & ptr, const LLUUID & id) {
                 sync.bump();
-- 
cgit v1.2.3


From f06ebd054bfbcf7e3b4c8deb097cbb5064b85366 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Sun, 14 Feb 2021 19:48:17 +0200
Subject: SL-14807 Missed a pool init in unused constructor, additional
 protections

---
 indra/llmessage/llcoproceduremanager.cpp | 11 +++++++++++
 indra/newview/llviewerassetstorage.cpp   |  1 +
 2 files changed, 12 insertions(+)

(limited to 'indra')

diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index c50d2bfd41..b94ec541e9 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -140,11 +140,22 @@ LLCoprocedureManager::~LLCoprocedureManager()
 
 void LLCoprocedureManager::initializePool(const std::string &poolName)
 {
+    poolMap_t::iterator it = mPoolMap.find(poolName);
+
+    if (it != mPoolMap.end())
+    {
+        // Pools are not supposed to be initialized twice
+        // Todo: ideally restrict init to STATE_FIRST
+        LL_ERRS() << "Pool is already present " << poolName << LL_ENDL;
+        return;
+    }
+
     // Attempt to look up a pool size in the configuration.  If found use that
     std::string keyName = "PoolSize" + poolName;
     int size = 0;
 
     LL_ERRS_IF(poolName.empty(), "CoprocedureManager") << "Poolname must not be empty" << LL_ENDL;
+    LL_INFOS("CoprocedureManager") << "Initializing pool " << poolName << LL_ENDL;
 
     if (mPropertyQueryFn)
     {
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index b345396c2f..19f2456ae6 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -115,6 +115,7 @@ LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *
       mCountSucceeded(0),
       mTotalBytesFetched(0)
 {
+    LLCoprocedureManager::instance().initializePool(VIEWER_ASSET_STORAGE_CORO_POOL);
 }
 
 
-- 
cgit v1.2.3


From b1ab29eeb6a2475395f92d26a3f07fdb304561f7 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Wed, 3 Mar 2021 19:27:22 +0200
Subject: SL-14939 Fixed the log spam

fix by Ansariel (https://vcs.firestormviewer.org/phoenix-firestorm/changeset/5f927b52fdfeebb5db595c7c60c711cee383820b)
---
 indra/llfilesystem/llfilesystem.cpp | 6 +++---
 indra/llfilesystem/llfilesystem.h   | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 64e0b9f193..053b52014e 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -72,14 +72,14 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil
 }
 
 // static
-bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type)
+bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error /*= 0*/)
 {
     std::string id_str;
     file_id.toString(id_str);
     const std::string extra_info = "";
     const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info);
 
-    LLFile::remove(filename.c_str());
+    LLFile::remove(filename.c_str(), suppress_error);
 
     return true;
 }
@@ -98,7 +98,7 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
     const std::string new_filename =  LLDiskCache::getInstance()->metaDataToFilepath(new_id_str, new_file_type, extra_info);
 
     // Rename needs the new file to not exist.
-    LLFileSystem::removeFile(new_file_id, new_file_type);
+    LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT);
 
     if (LLFile::rename(old_filename, new_filename) != 0)
     {
diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h
index 89bfff5798..d934a408c2 100644
--- a/indra/llfilesystem/llfilesystem.h
+++ b/indra/llfilesystem/llfilesystem.h
@@ -54,7 +54,7 @@ class LLFileSystem
         BOOL remove();
 
         static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type);
-        static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type);
+        static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error = 0);
         static bool renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,
                                const LLUUID& new_file_id, const LLAssetType::EType new_file_type);
         static S32 getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type);
-- 
cgit v1.2.3


From 88746478583711951d04a3ea709ccf1667ddf535 Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Wed, 3 Mar 2021 19:33:02 +0200
Subject: SL-14940 Fixed ignoring custom cache path

fix by Ansariel (https://vcs.firestormviewer.org/phoenix-firestorm/changeset/dace23b988af90a65ef57b0b9f540fc48d439dc3)
---
 indra/newview/llappviewer.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index ea0b950e62..0dc2c7d326 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4132,8 +4132,6 @@ bool LLAppViewer::initCache()
     const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100;
     const unsigned int disk_cache_bytes = disk_cache_mb * 1024 * 1024;
 	const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
-	const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
-	LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info);
 
 	bool texture_cache_mismatch = false;
 	if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
@@ -4181,6 +4179,9 @@ bool LLAppViewer::initCache()
 		gSavedSettings.setString("CacheLocationTopFolder", "");
 	}
 
+    const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
+    LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info);
+
 	if (!read_only)
 	{
 		if (mPurgeCache)
-- 
cgit v1.2.3


From 9a1698fd84472c47ef049344b7a5fe39685aa676 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Tue, 9 Mar 2021 16:07:02 +0200
Subject: SL-14967 New viewer notification for "Save Back To Object"

---
 indra/newview/skins/default/xui/en/notifications.xml | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 2f4da4f9b7..c2e8a18413 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10005,6 +10005,15 @@ Removal of the object &lt;nolink&gt;'[OBJ_NAME]'&lt;/nolink&gt; from the simulat
 Cannot save your selection because you do not have permission to modify the object &lt;nolink&gt;'[OBJ_NAME]'&lt;/nolink&gt;.
   </notification>
 
+
+  <notification
+   icon="alertmodal.tga"
+   name="NoTransNoSaveToContents"
+   type="notify">
+    <tag>fail</tag>
+    Cannot save &lt;nolink&gt;'[OBJ_NAME]'&lt;/nolink&gt; to object contents because you do not have permission to transfer the object's ownership.
+  </notification>
+
   <notification
    icon="alertmodal.tga"
    name="NoCopyNoSaveSelection"
-- 
cgit v1.2.3


From 3067f56b1f1be6506b0bddd2889854ad7fdf4d8a Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Tue, 9 Mar 2021 21:57:32 +0200
Subject: Revert "SL-14940 Fixed ignoring custom cache path"

This reverts commit 88746478583711951d04a3ea709ccf1667ddf535.
---
 indra/newview/llappviewer.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0dc2c7d326..ea0b950e62 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4132,6 +4132,8 @@ bool LLAppViewer::initCache()
     const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100;
     const unsigned int disk_cache_bytes = disk_cache_mb * 1024 * 1024;
 	const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
+	const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
+	LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info);
 
 	bool texture_cache_mismatch = false;
 	if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
@@ -4179,9 +4181,6 @@ bool LLAppViewer::initCache()
 		gSavedSettings.setString("CacheLocationTopFolder", "");
 	}
 
-    const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
-    LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info);
-
 	if (!read_only)
 	{
 		if (mPurgeCache)
-- 
cgit v1.2.3


From 43fbd41bfdb756877cedcc7a87638f5c0479930b Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Tue, 9 Mar 2021 21:57:41 +0200
Subject: Revert "SL-14939 Fixed the log spam"

This reverts commit b1ab29eeb6a2475395f92d26a3f07fdb304561f7.
---
 indra/llfilesystem/llfilesystem.cpp | 6 +++---
 indra/llfilesystem/llfilesystem.h   | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 053b52014e..64e0b9f193 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -72,14 +72,14 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil
 }
 
 // static
-bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error /*= 0*/)
+bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type)
 {
     std::string id_str;
     file_id.toString(id_str);
     const std::string extra_info = "";
     const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info);
 
-    LLFile::remove(filename.c_str(), suppress_error);
+    LLFile::remove(filename.c_str());
 
     return true;
 }
@@ -98,7 +98,7 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
     const std::string new_filename =  LLDiskCache::getInstance()->metaDataToFilepath(new_id_str, new_file_type, extra_info);
 
     // Rename needs the new file to not exist.
-    LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT);
+    LLFileSystem::removeFile(new_file_id, new_file_type);
 
     if (LLFile::rename(old_filename, new_filename) != 0)
     {
diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h
index d934a408c2..89bfff5798 100644
--- a/indra/llfilesystem/llfilesystem.h
+++ b/indra/llfilesystem/llfilesystem.h
@@ -54,7 +54,7 @@ class LLFileSystem
         BOOL remove();
 
         static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type);
-        static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error = 0);
+        static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type);
         static bool renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,
                                const LLUUID& new_file_id, const LLAssetType::EType new_file_type);
         static S32 getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type);
-- 
cgit v1.2.3


From a1d2b94b4c06c6ea33bf7f76c4c07578d26845f9 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 9 Mar 2021 21:37:02 +0200
Subject: SL-14807 Viewer crashes when creating an experience

Opening already open and recently created experience was crashing viewer due to viewer treating 'edit_experience' as part of floater's key.
---
 indra/newview/llfloaterexperienceprofile.cpp | 14 ++++++++++++++
 indra/newview/llfloaterexperienceprofile.h   |  2 ++
 2 files changed, 16 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp
index 2c9a8e64b7..a99a096ea7 100644
--- a/indra/newview/llfloaterexperienceprofile.cpp
+++ b/indra/newview/llfloaterexperienceprofile.cpp
@@ -211,6 +211,20 @@ bool LLFloaterExperienceProfile::experiencePermission( LLHandle<LLFloaterExperie
     return false;
 }
 
+bool LLFloaterExperienceProfile::matchesKey(const LLSD& key)
+{
+    if (key.has("experience_id"))
+    {
+        return mExperienceId == key["experience_id"].asUUID();
+    }
+    else if (key.isUUID())
+    {
+        return mExperienceId == key.asUUID();
+    }
+    // Assume NULL uuid
+    return mExperienceId.isNull();
+}
+
 
 void LLFloaterExperienceProfile::onClickEdit()
 {
diff --git a/indra/newview/llfloaterexperienceprofile.h b/indra/newview/llfloaterexperienceprofile.h
index 1394418d91..f9b6e2e2eb 100644
--- a/indra/newview/llfloaterexperienceprofile.h
+++ b/indra/newview/llfloaterexperienceprofile.h
@@ -51,6 +51,8 @@ public:
 
     LLFloaterExperienceProfile(const LLSD& data);
     virtual ~LLFloaterExperienceProfile();
+    
+    /* virtual */ bool matchesKey(const LLSD& key);
 
     LLUUID getExperienceId() const { return mExperienceId; }
     void setPreferences( const LLSD& content );
-- 
cgit v1.2.3


From 9505e14efe65f426ebf4cf85ad4b876c20d0be64 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 10 Mar 2021 18:04:22 +0200
Subject: SL-14975 SL-14384 viewer crashes because of large chat groups

1. Due to desync participant can be NULL - added NULL checks
2. With large backlog of events, closing and then opening a goup session was causing a crash due to obsolete events - added cleanup for backlog
3. In some cases events were accumulating faster than they were processed - ensured that after certain point event processing scales up with a backlog
---
 indra/newview/llconversationmodel.cpp   |  4 +-
 indra/newview/llconversationview.cpp    | 11 ++++--
 indra/newview/llfloaterimcontainer.cpp  | 69 ++++++++++++++++++++++++++-------
 indra/newview/llfloaterimcontainer.h    |  5 ++-
 indra/newview/llfloaterimsessiontab.cpp |  5 ++-
 5 files changed, 70 insertions(+), 24 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 4aa74a550c..27b1f3d20a 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -355,7 +355,7 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const
 	for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
 	{
 		participant = dynamic_cast<LLConversationItemParticipant*>(*iter);
-		if (participant->hasSameValue(participant_id))
+		if (participant && participant->hasSameValue(participant_id))
 		{
 			break;
 		}
@@ -466,7 +466,7 @@ const bool LLConversationItemSession::getTime(F64& time) const
 	{
 		participant = dynamic_cast<LLConversationItemParticipant*>(*iter);
 		F64 participant_time;
-		if (participant->getTime(participant_time))
+		if (participant && participant->getTime(participant_time))
 		{
 			has_time = true;
 			most_recent_time = llmax(most_recent_time,participant_time);
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index 093e772abe..7c1db98b3f 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -617,10 +617,13 @@ void LLConversationViewParticipant::refresh()
 {
 	// Refresh the participant view from its model data
 	LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());
-	participant_model->resetRefresh();
-	
-	// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
-	mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
+    if (participant_model)
+    {
+        participant_model->resetRefresh();
+
+        // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
+        mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
+    }
 
 	// Do the regular upstream refresh
 	LLFolderViewItem::refresh();
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index c6e9069d09..007c0d3b22 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -59,7 +59,9 @@
 #include "boost/foreach.hpp"
 
 
-const S32 EVENTS_PER_IDLE_LOOP = 100;
+const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80;
+const S32 EVENTS_PER_IDLE_LOOP_BACKGROUND = 40;
+const F32 EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE = 0.01f; // process a minimum of 1% of total events per frame
 
 //
 // LLFloaterIMContainer
@@ -416,8 +418,11 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate()
 		while (current_participant_model != end_participant_model)
 		{
 			LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
-			// Get the avatar name for this participant id from the cache and update the model
-			participant_model->updateName();
+            if (participant_model)
+            {
+                // Get the avatar name for this participant id from the cache and update the model
+                participant_model->updateName();
+            }
 			// Next participant
 			current_participant_model++;
 		}
@@ -464,8 +469,11 @@ void LLFloaterIMContainer::idleUpdate()
                 while (current_participant_model != end_participant_model)
                 {
                     LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
-                    participant_model->setModeratorOptionsVisible(is_moderator);
-                    participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
+                    if (participant_model)
+                    {
+                        participant_model->setModeratorOptionsVisible(is_moderator);
+                        participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
+                    }
 
                     current_participant_model++;
                 }
@@ -498,20 +506,49 @@ void LLFloaterIMContainer::idleUpdate()
 
 void LLFloaterIMContainer::idleProcessEvents()
 {
-	if (!mConversationEventQueue.empty())
-	{
-		S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP);
-		for (S32 i = 0; i < events_to_handle; i++)
-		{
-			handleConversationModelEvent(mConversationEventQueue.back());
-			mConversationEventQueue.pop_back();
-		}
-	}
+    LLUUID current_session_id = getSelectedSession();
+    conversations_items_deque::iterator iter = mConversationEventQueue.begin();
+    conversations_items_deque::iterator end = mConversationEventQueue.end();
+    while (iter != end)
+    {
+        std::deque<LLSD> &events = iter->second;
+        if (!events.empty())
+        {
+            S32 events_to_handle;
+            S32 query_size = (S32)events.size();
+            if (current_session_id == iter->first)
+            {
+                events_to_handle = EVENTS_PER_IDLE_LOOP_CURRENT_SESSION;
+            }
+            else
+            {
+                events_to_handle = EVENTS_PER_IDLE_LOOP_BACKGROUND;
+            }
+
+            if (events_to_handle <= query_size)
+            {
+                // Some groups can be very large and can generate huge amount of updates, scale processing up to keep up
+                events_to_handle = llmax(events_to_handle, (S32)(query_size * EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE));
+            }
+            else
+            {
+                events_to_handle = query_size;
+            }
+
+            for (S32 i = 0; i < events_to_handle; i++)
+            {
+                handleConversationModelEvent(events.back());
+                events.pop_back();
+            }
+        }
+        iter++;
+    }
 }
 
 bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 {
-	mConversationEventQueue.push_front(event);
+	LLUUID id = event.get("session_uuid").asUUID();
+	mConversationEventQueue[id].push_front(event);
 	return true;
 }
 
@@ -1822,6 +1859,8 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
 	// Suppress the conversation items and widgets from their respective maps
 	mConversationsItems.erase(uuid);
 	mConversationsWidgets.erase(uuid);
+	// Clear event query (otherwise reopening session in some way can bombard session with stale data)
+	mConversationEventQueue.erase(uuid);
 	
 	// Don't let the focus fall IW, select and refocus on the first conversation in the list
 	if (change_focus)
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 468b47f1f1..b4a9d377ab 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -229,9 +229,10 @@ private:
 	conversations_widgets_map mConversationsWidgets;
 	LLConversationViewModel mConversationViewModel;
 	LLFolderView* mConversationsRoot;
-	LLEventStream mConversationsEventStream; 
+	LLEventStream mConversationsEventStream;
 
-	std::deque<LLSD> mConversationEventQueue;
+	typedef std::map<LLUUID, std::deque<LLSD> > conversations_items_deque;
+	conversations_items_deque mConversationEventQueue;
 
 	LLTimer mParticipantRefreshTimer;
 };
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index d604d0a789..80165f9b9a 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -492,7 +492,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
 	while (current_participant_model != end_participant_model)
 	{
 		LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model);
-		addConversationViewParticipant(participant_model);
+        if (participant_model)
+        {
+            addConversationViewParticipant(participant_model);
+        }
 		current_participant_model++;
 	}
 }
-- 
cgit v1.2.3


From 4076208a72dbcb36adbdfcca86a9fbcc12d2bda3 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 10 Mar 2021 20:28:00 +0200
Subject: SL-14961 Bugsplat logging

---
 indra/newview/llappviewer.cpp                      | 27 ++++++++++++++++
 indra/newview/llappviewer.h                        |  2 ++
 indra/newview/llappviewerwin32.cpp                 | 36 ++++++++++++++++++----
 indra/newview/llviewermenu.cpp                     | 32 +++++++++++++++++++
 indra/newview/skins/default/xui/en/menu_viewer.xml | 12 ++++++++
 5 files changed, 103 insertions(+), 6 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f518704e06..a1d73acfa5 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -5549,6 +5549,33 @@ void LLAppViewer::forceErrorDriverCrash()
 	glDeleteTextures(1, NULL);
 }
 
+void LLAppViewer::forceErrorCoroutineCrash()
+{
+    LL_WARNS() << "Forcing a crash in LLCoros" << LL_ENDL;
+    LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw std::exception("A deliberate crash from LLCoros"); });
+}
+
+void LLAppViewer::forceErrorThreadCrash()
+{
+    class LLCrashTestThread : public LLThread
+    {
+    public:
+
+        LLCrashTestThread() : LLThread("Crash logging test thread")
+        {
+        }
+
+        void run()
+        {
+            LL_ERRS() << "This is a deliberate llerror in thread" << LL_ENDL;
+        }
+    };
+
+    LL_WARNS() << "This is a deliberate crash in a thread" << LL_ENDL;
+    LLCrashTestThread *thread = new LLCrashTestThread();
+    thread->start();
+}
+
 void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
 {
 	if(!mMainloopTimeout)
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 5332fe2deb..6db45583eb 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -150,6 +150,8 @@ public:
     virtual void forceErrorInfiniteLoop();
     virtual void forceErrorSoftwareException();
     virtual void forceErrorDriverCrash();
+    virtual void forceErrorCoroutineCrash();
+    virtual void forceErrorThreadCrash();
 
 	// The list is found in app_settings/settings_files.xml
 	// but since they are used explicitly in code,
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 9b1c0d1f8b..bb6156e209 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -609,6 +609,13 @@ bool LLAppViewerWin32::init()
 #else // LL_BUGSPLAT
 #pragma message("Building with BugSplat")
 
+    if (!isSecondInstance())
+    {
+        // Cleanup previous session
+        std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
+        LLFile::remove(log_file, ENOENT);
+    }
+
 	std::string build_data_fname(
 		gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json"));
 	// Use llifstream instead of std::ifstream because LL_PATH_EXECUTABLE
@@ -616,7 +623,7 @@ bool LLAppViewerWin32::init()
 	llifstream inf(build_data_fname.c_str());
 	if (! inf.is_open())
 	{
-		LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname
+		LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname
 				   << "'" << LL_ENDL;
 	}
 	else
@@ -626,7 +633,7 @@ bool LLAppViewerWin32::init()
 		if (! reader.parse(inf, build_data, false)) // don't collect comments
 		{
 			// gah, the typo is baked into Json::Reader API
-			LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname
+			LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname
 					   << "': " << reader.getFormatedErrorMessages() << LL_ENDL;
 		}
 		else
@@ -634,7 +641,7 @@ bool LLAppViewerWin32::init()
 			Json::Value BugSplat_DB = build_data["BugSplat DB"];
 			if (! BugSplat_DB)
 			{
-				LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
+				LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '"
 						   << build_data_fname << "'" << LL_ENDL;
 			}
 			else
@@ -645,18 +652,35 @@ bool LLAppViewerWin32::init()
 													   LL_VIEWER_VERSION_PATCH << '.' <<
 													   LL_VIEWER_VERSION_BUILD));
 
+                DWORD dwFlags = MDSF_NONINTERACTIVE | // automatically submit report without prompting
+                                MDSF_PREVENTHIJACKING; // disallow swiping Exception filter
+
+                bool needs_log_file = !isSecondInstance() && debugLoggingEnabled("BUGSPLAT");
+                if (needs_log_file)
+                {
+                    // Startup only!
+                    LL_INFOS("BUGSPLAT") << "Engaged BugSplat logging to bugsplat.log" << LL_ENDL;
+                    dwFlags |= MDSF_LOGFILE | MDSF_LOG_VERBOSE;
+                }
+
 				// have to convert normal wide strings to strings of __wchar_t
 				sBugSplatSender = new MiniDmpSender(
 					WCSTR(BugSplat_DB.asString()),
 					WCSTR(LL_TO_WSTRING(LL_VIEWER_CHANNEL)),
 					WCSTR(version_string),
 					nullptr,              // szAppIdentifier -- set later
-					MDSF_NONINTERACTIVE | // automatically submit report without prompting
-					MDSF_PREVENTHIJACKING); // disallow swiping Exception filter
+					dwFlags);
 				sBugSplatSender->setCallback(bugsplatSendLog);
 
+                if (needs_log_file)
+                {
+                    // Log file will be created in %TEMP%, but it will be moved into logs folder in case of crash
+                    std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "bugsplat.log");
+                    sBugSplatSender->setLogFilePath(WCSTR(log_file));
+                }
+
 				// engage stringize() overload that converts from wstring
-				LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
+				LL_INFOS("BUGSPLAT") << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL)
 						   << ' ' << stringize(version_string) << ')' << LL_ENDL;
 			} // got BugSplat_DB
 		} // parsed build_data.json
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 29888fe9fd..2299f710f2 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -286,6 +286,8 @@ void force_error_bad_memory_access(void *);
 void force_error_infinite_loop(void *);
 void force_error_software_exception(void *);
 void force_error_driver_crash(void *);
+void force_error_coroutine_crash(void *);
+void force_error_thread_crash(void *);
 
 void handle_force_delete(void*);
 void print_object_info(void*);
@@ -2363,6 +2365,24 @@ class LLAdvancedForceErrorDriverCrash : public view_listener_t
 	}
 };
 
+class LLAdvancedForceErrorCoroutineCrash : public view_listener_t
+{
+    bool handleEvent(const LLSD& userdata)
+    {
+        force_error_coroutine_crash(NULL);
+        return true;
+    }
+};
+
+class LLAdvancedForceErrorThreadCrash : public view_listener_t
+{
+    bool handleEvent(const LLSD& userdata)
+    {
+        force_error_thread_crash(NULL);
+        return true;
+    }
+};
+
 class LLAdvancedForceErrorDisconnectViewer : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -8035,6 +8055,16 @@ void force_error_driver_crash(void *)
     LLAppViewer::instance()->forceErrorDriverCrash();
 }
 
+void force_error_coroutine_crash(void *)
+{
+    LLAppViewer::instance()->forceErrorCoroutineCrash();
+}
+
+void force_error_thread_crash(void *)
+{
+    LLAppViewer::instance()->forceErrorThreadCrash();
+}
+
 class LLToolsUseSelectionForGrid : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
@@ -9202,6 +9232,8 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop");
 	view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException");
 	view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash");
+    view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash");
+    view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash");
 	view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer");
 
 	// Advanced (toplevel)
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 5fa1847d1b..3ce55be554 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2437,6 +2437,18 @@ function="World.EnvPreset"
                 <menu_item_call.on_click
                  function="Advanced.ForceErrorSoftwareException" />
             </menu_item_call>
+            <menu_item_call
+             label="Force a Crash in a Coroutine"
+             name="Force a Crash in a Coroutine">
+                <menu_item_call.on_click
+                 function="Advanced.ForceErrorCoroutineCrash" />
+            </menu_item_call>
+            <menu_item_call
+             label="Force a Crash in a Thread"
+             name="Force a Crash in a Thread">
+                <menu_item_call.on_click
+                 function="Advanced.ForceErrorThreadCrash" />
+            </menu_item_call>
             <menu_item_call
              label="Force Disconnect Viewer"
              name="Force Disconnect Viewer">
-- 
cgit v1.2.3


From ed98ebb8115bffc5cf78ec00e33adf2243c55f0d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 12 Mar 2021 18:19:53 +0200
Subject: SL-14961 Coroutine crash was not reported to bugsplat

---
 indra/llcommon/llapp.h             |  4 +++
 indra/llcommon/llcoros.cpp         | 58 +++++++++++++++++++++++++++-----------
 indra/llcommon/llcoros.h           |  7 +++--
 indra/newview/llappviewer.cpp      |  2 +-
 indra/newview/llappviewerwin32.cpp | 10 +++++++
 indra/newview/llappviewerwin32.h   | 22 ++++++++-------
 6 files changed, 72 insertions(+), 31 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 245c73e3a2..5fa91b8bf5 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -259,6 +259,10 @@ public:
 	  */
 	LLRunner& getRunner() { return mRunner; }
 
+#ifdef LL_WINDOWS
+    virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { }
+#endif
+
 public:
 	typedef std::map<std::string, std::string> string_map;
 	string_map mOptionMap;	// Contains all command-line options and arguments in a map
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 262929006d..111c50af93 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -255,8 +255,21 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
 
 static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
 
-U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
+U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name)
 {
+    // C++ exceptions were logged in toplevelTryWrapper, but not SEH
+    // log SEH exceptions here, to make sure it gets into bugsplat's 
+    // report and because __try won't allow std::string operations
+    if (code != STATUS_MSC_EXCEPTION)
+    {
+        LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL;
+    }
+    // Handle bugsplat here, since GetExceptionInformation() can only be
+    // called from within filter for __except(filter), not from __except's {}
+    // Bugsplat should get all exceptions, C++ and SEH
+    LLApp::instance()->reportCrashToBugsplat(exception_infop);
+
+    // Only convert non C++ exceptions.
     if (code == STATUS_MSC_EXCEPTION)
     {
         // C++ exception, go on
@@ -269,29 +282,29 @@ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
     }
 }
 
-void LLCoros::winlevel(const callable_t& callable)
+void LLCoros::winlevel(const std::string& name, const callable_t& callable)
 {
     __try
     {
-        callable();
+        toplevelTryWrapper(name, callable);
     }
-    __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+    __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))
     {
-        // convert to C++ styled exception
+        // convert to C++ styled exception for handlers other than bugsplat
         // Note: it might be better to use _se_set_translator
         // if you want exception to inherit full callstack
-        char integer_string[32];
-        sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+        //
+        // in case of bugsplat this will get to exceptionTerminateHandler and
+        // looks like fiber will terminate application after that
+        char integer_string[512];
+        sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode());
         throw std::exception(integer_string);
     }
 }
 
 #endif
 
-// Top-level wrapper around caller's coroutine callable.
-// Normally we like to pass strings and such by const reference -- but in this
-// case, we WANT to copy both the name and the callable to our local stack!
-void LLCoros::toplevel(std::string name, callable_t callable)
+void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable)
 {
     // keep the CoroData on this top-level function's stack frame
     CoroData corodata(name);
@@ -301,16 +314,12 @@ void LLCoros::toplevel(std::string name, callable_t callable)
     // run the code the caller actually wants in the coroutine
     try
     {
-#if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD
-        winlevel(callable);
-#else
         callable();
-#endif
     }
     catch (const Stop& exc)
     {
         LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
-                            << exc.what() << LL_ENDL;
+            << exc.what() << LL_ENDL;
     }
     catch (const LLContinueError&)
     {
@@ -323,10 +332,25 @@ void LLCoros::toplevel(std::string name, callable_t callable)
     {
         // Any OTHER kind of uncaught exception will cause the viewer to
         // crash, hopefully informatively.
-        CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
+        LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
+        // to not modify callstack
+        throw;
     }
 }
 
+// Top-level wrapper around caller's coroutine callable.
+// Normally we like to pass strings and such by const reference -- but in this
+// case, we WANT to copy both the name and the callable to our local stack!
+void LLCoros::toplevel(std::string name, callable_t callable)
+{
+#if LL_WINDOWS
+    // Can not use __try in functions that require unwinding, so use one more wrapper
+    winlevel(name, callable);
+#else
+    toplevelTryWrapper(name, callable);
+#endif
+}
+
 //static
 void LLCoros::checkStop()
 {
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 38c2356c99..6c0bec3ef9 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -290,11 +290,12 @@ public:
 
 private:
     std::string generateDistinctName(const std::string& prefix) const;
-    void toplevel(std::string name, callable_t callable);
-    struct CoroData;
 #if LL_WINDOWS
-    static void winlevel(const callable_t& callable);
+    void winlevel(const std::string& name, const callable_t& callable);
 #endif
+    void toplevelTryWrapper(const std::string& name, const callable_t& callable);
+    void toplevel(std::string name, callable_t callable);
+    struct CoroData;
     static CoroData& get_CoroData(const std::string& caller);
 
     S32 mStackSize;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a1d73acfa5..7c2f622abd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -5552,7 +5552,7 @@ void LLAppViewer::forceErrorDriverCrash()
 void LLAppViewer::forceErrorCoroutineCrash()
 {
     LL_WARNS() << "Forcing a crash in LLCoros" << LL_ENDL;
-    LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw std::exception("A deliberate crash from LLCoros"); });
+    LLCoros::instance().launch("LLAppViewer::crashyCoro", [] {throw LLException("A deliberate crash from LLCoros"); });
 }
 
 void LLAppViewer::forceErrorThreadCrash()
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index bb6156e209..ce36d3458e 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -709,6 +709,16 @@ bool LLAppViewerWin32::cleanup()
 	return result;
 }
 
+void LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
+{
+#if defined(LL_BUGSPLAT)
+    if (sBugSplatSender)
+    {
+        sBugSplatSender->createReport((EXCEPTION_POINTERS*)pExcepInfo);
+    }
+#endif // LL_BUGSPLAT
+}
+
 void LLAppViewerWin32::initLoggingAndGetLastDuration()
 {
 	LLAppViewer::initLoggingAndGetLastDuration();
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index c5fae6a3a3..83ae875a15 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -40,20 +40,22 @@ public:
 	//
 	// Main application logic
 	//
-	virtual bool init(); // Override to do application initialization
-	virtual bool cleanup();
+	bool init() override; // Override to do application initialization
+    bool cleanup() override;
+
+    void reportCrashToBugsplat(void* pExcepInfo) override;
 
 protected:
-	virtual void initLoggingAndGetLastDuration(); // Override to clean stack_trace info.
-	virtual void initConsole(); // Initialize OS level debugging console.
-	virtual bool initHardwareTest(); // Win32 uses DX9 to test hardware.
-	virtual bool initParseCommandLine(LLCommandLineParser& clp);
+	void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info.
+	void initConsole() override; // Initialize OS level debugging console.
+	bool initHardwareTest() override; // Win32 uses DX9 to test hardware.
+	bool initParseCommandLine(LLCommandLineParser& clp) override;
 
-	virtual bool beingDebugged();
-	virtual bool restoreErrorTrap();
-	virtual void initCrashReporting(bool reportFreeze); 
+	bool beingDebugged() override;
+	bool restoreErrorTrap() override;
+	void initCrashReporting(bool reportFreeze) override;
 
-	virtual bool sendURLToOtherInstance(const std::string& url);
+	bool sendURLToOtherInstance(const std::string& url) override;
 
 	std::string generateSerialNumber();
 
-- 
cgit v1.2.3


From 60d62c767be3576cb674a817b90028951d6ee3b0 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Tue, 16 Mar 2021 16:18:56 +0100
Subject: SL-14999 - cppfeatures test file for examples and compiler
 conformance verification

---
 indra/newview/CMakeLists.txt             |   4 +
 indra/newview/tests/cppfeatures_test.cpp | 127 +++++++++++++++++++++++++++++++
 2 files changed, 131 insertions(+)
 create mode 100644 indra/newview/tests/cppfeatures_test.cpp

(limited to 'indra')

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3439951e80..9c11f8aa87 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2520,6 +2520,10 @@ if (LL_TESTS)
     ${BOOST_CONTEXT_LIBRARY}
   )
 
+  LL_ADD_INTEGRATION_TEST(cppfeatures
+    ""
+    "${test_libs}"
+    )
   LL_ADD_INTEGRATION_TEST(llsechandler_basic
     llsechandler_basic.cpp
     "${test_libs}"
diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
new file mode 100644
index 0000000000..15aa1cd6d6
--- /dev/null
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -0,0 +1,127 @@
+/**
+ * @file cppfeatures_test
+ * @author Vir
+ * @date 2021-03
+ * @brief cpp features
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Tests related to newer C++ features, for verifying support across compilers and platforms
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+
+struct cpp_features_test {};
+typedef test_group<cpp_features_test> cpp_features_test_t;
+typedef cpp_features_test_t::object cpp_features_test_object_t;
+tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
+
+// bracket initializers
+// Can initialize containers or values using curly brackets
+template<> template<>
+void cpp_features_test_object_t::test<1>()
+{
+	S32 explicit_val{3};
+	ensure(explicit_val==3);
+
+	S32 default_val{};
+	ensure(default_val==0);
+	
+	std::vector<S32> fibs{1,1,2,3,5};
+	ensure(fibs[4]==5);
+}
+
+// auto
+//
+// https://en.cppreference.com/w/cpp/language/auto
+// 
+// Can use auto in place of a more complex type specification, if the compiler can infer the type
+template<> template<>
+void cpp_features_test_object_t::test<2>()
+{
+	std::vector<S32> numbers{3,6,9};
+
+	// auto element
+	auto& aval = numbers[1];
+	ensure("auto element", aval==6);
+
+	// auto iterator (non-const)
+	auto it = numbers.rbegin();
+	*it += 1;
+	S32 val = *it;
+	ensure("auto iterator", val==10);
+}
+
+// range for
+//
+// https://en.cppreference.com/w/cpp/language/range-for
+//
+// Can iterate over containers without explicit iterator
+template<> template<>
+void cpp_features_test_object_t::test<3>()
+{
+
+	// Traditional iterator for with container
+	//
+	// Problems:
+	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
+	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
+	std::vector<S32> numbers{3,6,9};
+	for (auto it = numbers.begin(); it != numbers.end(); ++it)
+	{
+		auto& n = *it;
+		n *= 2;
+	}
+	ensure("iterator for vector", numbers[2]==18);
+
+	// Range for with container
+	//
+	// Under the hood, this is doing the same thing as the traditional
+	// for loop above. Still uses begin() and end() but you don't have
+	// to access them directly.
+	std::vector<S32> numbersb{3,6,9};
+	for (auto& n: numbersb)
+	{
+		n *= 2;
+	}
+	ensure("range for vector", numbersb[2]==18);
+
+	// Range for over a C-style array.
+	//
+	// This is handy because the language determines the range automatically.
+	// Getting this right manually is a little trickier.
+	S32 pows[] = {1,2,4,8,16};
+	S32 sum{};
+	for (const auto& v: pows)
+	{
+		sum += v;
+	}
+	ensure("for C-array", sum==31);
+}
+
+
+
+}
-- 
cgit v1.2.3


From 47b3078c93a763f67103ff67f0fe8b6ac5794370 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Mar 2021 13:54:18 +0100
Subject: SL-14999 - C++ feature tests

---
 indra/newview/tests/cppfeatures_test.cpp | 372 ++++++++++++++++++++-----------
 1 file changed, 245 insertions(+), 127 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index 15aa1cd6d6..8399bb12ff 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -1,127 +1,245 @@
-/**
- * @file cppfeatures_test
- * @author Vir
- * @date 2021-03
- * @brief cpp features
- *
- * $LicenseInfo:firstyear=2021&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2021, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-// Tests related to newer C++ features, for verifying support across compilers and platforms
-
-#include "linden_common.h"
-#include "../test/lltut.h"
-
-namespace tut
-{
-
-struct cpp_features_test {};
-typedef test_group<cpp_features_test> cpp_features_test_t;
-typedef cpp_features_test_t::object cpp_features_test_object_t;
-tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
-
-// bracket initializers
-// Can initialize containers or values using curly brackets
-template<> template<>
-void cpp_features_test_object_t::test<1>()
-{
-	S32 explicit_val{3};
-	ensure(explicit_val==3);
-
-	S32 default_val{};
-	ensure(default_val==0);
-	
-	std::vector<S32> fibs{1,1,2,3,5};
-	ensure(fibs[4]==5);
-}
-
-// auto
-//
-// https://en.cppreference.com/w/cpp/language/auto
-// 
-// Can use auto in place of a more complex type specification, if the compiler can infer the type
-template<> template<>
-void cpp_features_test_object_t::test<2>()
-{
-	std::vector<S32> numbers{3,6,9};
-
-	// auto element
-	auto& aval = numbers[1];
-	ensure("auto element", aval==6);
-
-	// auto iterator (non-const)
-	auto it = numbers.rbegin();
-	*it += 1;
-	S32 val = *it;
-	ensure("auto iterator", val==10);
-}
-
-// range for
-//
-// https://en.cppreference.com/w/cpp/language/range-for
-//
-// Can iterate over containers without explicit iterator
-template<> template<>
-void cpp_features_test_object_t::test<3>()
-{
-
-	// Traditional iterator for with container
-	//
-	// Problems:
-	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
-	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
-	std::vector<S32> numbers{3,6,9};
-	for (auto it = numbers.begin(); it != numbers.end(); ++it)
-	{
-		auto& n = *it;
-		n *= 2;
-	}
-	ensure("iterator for vector", numbers[2]==18);
-
-	// Range for with container
-	//
-	// Under the hood, this is doing the same thing as the traditional
-	// for loop above. Still uses begin() and end() but you don't have
-	// to access them directly.
-	std::vector<S32> numbersb{3,6,9};
-	for (auto& n: numbersb)
-	{
-		n *= 2;
-	}
-	ensure("range for vector", numbersb[2]==18);
-
-	// Range for over a C-style array.
-	//
-	// This is handy because the language determines the range automatically.
-	// Getting this right manually is a little trickier.
-	S32 pows[] = {1,2,4,8,16};
-	S32 sum{};
-	for (const auto& v: pows)
-	{
-		sum += v;
-	}
-	ensure("for C-array", sum==31);
-}
-
-
-
-}
+/**
+ * @file cppfeatures_test
+ * @author Vir
+ * @date 2021-03
+ * @brief cpp features
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Tests related to newer C++ features, for verifying support across compilers and platforms
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+namespace tut
+{
+
+struct cpp_features_test {};
+typedef test_group<cpp_features_test> cpp_features_test_t;
+typedef cpp_features_test_t::object cpp_features_test_object_t;
+tut::cpp_features_test_t tut_cpp_features_test("LLCPPFeatures");
+
+// bracket initializers
+// Can initialize containers or values using curly brackets
+template<> template<>
+void cpp_features_test_object_t::test<1>()
+{
+	S32 explicit_val{3};
+	ensure(explicit_val==3);
+
+	S32 default_val{};
+	ensure(default_val==0);
+	
+	std::vector<S32> fibs{1,1,2,3,5};
+	ensure(fibs[4]==5);
+}
+
+// auto
+//
+// https://en.cppreference.com/w/cpp/language/auto
+// 
+// Can use auto in place of a more complex type specification, if the compiler can infer the type
+template<> template<>
+void cpp_features_test_object_t::test<2>()
+{
+	std::vector<S32> numbers{3,6,9};
+
+	// auto element
+	auto& aval = numbers[1];
+	ensure("auto element", aval==6);
+
+	// auto iterator (non-const)
+	auto it = numbers.rbegin();
+	*it += 1;
+	S32 val = *it;
+	ensure("auto iterator", val==10);
+}
+
+// range for
+//
+// https://en.cppreference.com/w/cpp/language/range-for
+//
+// Can iterate over containers without explicit iterator
+template<> template<>
+void cpp_features_test_object_t::test<3>()
+{
+
+	// Traditional iterator for with container
+	//
+	// Problems:
+	// * Have to create a new variable for the iterator, which is unrelated to the problem you're trying to solve.
+	// * Redundant and somewhat fragile. Have to make sure begin() and end() are both from the right container.
+	std::vector<S32> numbers{3,6,9};
+	for (auto it = numbers.begin(); it != numbers.end(); ++it)
+	{
+		auto& n = *it;
+		n *= 2;
+	}
+	ensure("iterator for vector", numbers[2]==18);
+
+	// Range for with container
+	//
+	// Under the hood, this is doing the same thing as the traditional
+	// for loop above. Still uses begin() and end() but you don't have
+	// to access them directly.
+	std::vector<S32> numbersb{3,6,9};
+	for (auto& n: numbersb)
+	{
+		n *= 2;
+	}
+	ensure("range for vector", numbersb[2]==18);
+
+	// Range for over a C-style array.
+	//
+	// This is handy because the language determines the range automatically.
+	// Getting this right manually is a little trickier.
+	S32 pows[] = {1,2,4,8,16};
+	S32 sum{};
+	for (const auto& v: pows)
+	{
+		sum += v;
+	}
+	ensure("for C-array", sum==31);
+}
+
+// override specifier
+//
+// https://en.cppreference.com/w/cpp/language/override
+//
+// Specify that a particular class function is an override of a virtual function.
+// Benefits:
+// * Makes code somewhat easier to read by showing intent.
+// * Prevents mistakes where you think something is an override but it doesn't actually match the declaration in the parent class.
+// Drawbacks:
+// * Some compilers require that any class using override must use it consistently for all functions. 
+//   This makes switching a class to use override a lot more work. 
+
+class Foo
+{
+public:
+	virtual bool is_happy() const = 0;
+};
+
+class Bar: public Foo
+{
+public:
+	bool is_happy() const override { return true; } 
+	// Override would fail: non-const declaration doesn't match parent 
+	// bool is_happy() override { return true; } 
+	// Override would fail: wrong name
+	// bool is_happx() override { return true; } 
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<4>()
+{
+	Bar b;
+	ensure("override", b.is_happy());
+}
+
+// final
+//
+// https://en.cppreference.com/w/cpp/language/final: "Specifies that a
+// virtual function cannot be overridden in a derived class or that a
+// class cannot be inherited from."
+
+class Vehicle
+{
+public:
+	virtual bool has_wheels() const = 0;
+};
+
+class WheeledVehicle: public Vehicle
+{
+public:
+	virtual bool has_wheels() const final override { return true; }
+};
+
+class Bicycle: public WheeledVehicle
+{
+public:
+	// Error: can't override final version in WheeledVehicle 
+	// virtual bool has_wheels() override const { return true; }
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<5>()
+{
+	Bicycle bi;
+	ensure("final", bi.has_wheels());
+}
+
+// deleted function declaration
+//
+// https://en.cppreference.com/w/cpp/language/function#Deleted_functions
+//
+// Typical case: copy constructor doesn't make sense for a particular class, so you want to make
+// sure the no one tries to copy-construct an instance of the class, and that the
+// compiler won't generate a copy constructor for  you automatically.
+// Traditional fix is to declare a
+// copy constructor but never implement it, giving you a link-time error if anyone tries to use it.
+// Now you can explicitly declare a function to be deleted, which has at least two advantages over
+// the old way:
+// * Makes the intention clear
+// * Creates an error sooner, at compile time
+
+class DoNotCopy
+{
+public:
+	DoNotCopy() {}
+	DoNotCopy(const DoNotCopy& ref) = delete;
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<6>()
+{
+	DoNotCopy nc; // OK, default constructor
+	//DoNotCopy nc2(nc); // No, can't copy
+	//DoNotCopy nc3 = nc; // No, this also calls copy constructor (even though it looks like an assignment)
+}
+
+// defaulted function declaration
+//
+// https://en.cppreference.com/w/cpp/language/function#Function_definition
+//
+// What about the complementary case to the deleted function declaration, where you want a copy constructor
+// and are happy with the default implementation the compiler will make (memberwise copy).
+// Now you can explicitly declare that too.
+// Usage: I guess it makes the intent clearer, but otherwise not obviously useful.
+class DefaultCopyOK
+{
+public:
+	DefaultCopyOK() {}
+	DefaultCopyOK(const DefaultCopyOK&) = default;
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<7>()
+{
+	DefaultCopyOK d; // OK
+	DefaultCopyOK d2(d); // OK
+	DefaultCopyOK d3 = d; // OK
+}
+
+
+} // namespace tut
-- 
cgit v1.2.3


From 1a3c5c57396c8faacd18adb2bd830f6907c4d66f Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Mar 2021 16:04:32 +0100
Subject: SL-14999 - test update

---
 indra/newview/tests/cppfeatures_test.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index 8399bb12ff..67671dc65e 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -229,8 +229,11 @@ void cpp_features_test_object_t::test<6>()
 class DefaultCopyOK
 {
 public:
-	DefaultCopyOK() {}
+	DefaultCopyOK(): mVal(123) {}
 	DefaultCopyOK(const DefaultCopyOK&) = default;
+	S32 val() const { return mVal; }
+private:
+	S32 mVal;
 };
 
 template<> template<>
@@ -239,6 +242,9 @@ void cpp_features_test_object_t::test<7>()
 	DefaultCopyOK d; // OK
 	DefaultCopyOK d2(d); // OK
 	DefaultCopyOK d3 = d; // OK
+	ensure("default copy d", d.val()==123);
+	ensure("default copy d2", d.val()==d2.val());
+	ensure("default copy d3", d.val()==d3.val());
 }
 
 
-- 
cgit v1.2.3


From 41a10cceb45f88d3ab433aa129eafd2ffa40256d Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Wed, 17 Mar 2021 20:53:36 +0100
Subject: SL-14999 - more c++ feature tests

---
 indra/newview/tests/cppfeatures_test.cpp | 89 ++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index 67671dc65e..bfaa83140d 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -247,5 +247,94 @@ void cpp_features_test_object_t::test<7>()
 	ensure("default copy d3", d.val()==d3.val());
 }
 
+// initialize class members inline
+//
+// https://en.cppreference.com/w/cpp/language/data_members#Member_initialization
+//
+// Default class member values can be set where they are declared, using either brackets or =
+
+// It is preferred to skip creating a constructor if all the work can be done by inline initialization:
+// http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html#c45-dont-define-a-default-constructor-that-only-initializes-data-members-use-in-class-member-initializers-instead
+//
+class InitInline
+{
+public:
+	S32 mFoo{10};
+};
+
+class InitInlineWithConstructor
+{
+public:
+	// Here mFoo is not specified, so you will get the default value of 10.
+	// mBar is specified, so 25 will override the default value.
+	InitInlineWithConstructor():
+		mBar(25)
+	{}
+
+	// Default values set using two different styles, same effect.
+	S32 mFoo{10};
+	S32 mBar = 20;
+};
+
+template<> template<>
+void cpp_features_test_object_t::test<8>()
+{
+	InitInline ii;
+	ensure("init member inline 1", ii.mFoo==10);
+
+	InitInlineWithConstructor iici;
+	ensure("init member inline 2", iici.mFoo=10);
+	ensure("init member inline 3", iici.mBar==25);
+}
+
+// constexpr
+//
+// https://en.cppreference.com/w/cpp/language/constexpr
+//
+// Various things can be computed at compile time, and flagged as constexpr.
+constexpr S32 compute2() { return 2; }
+
+constexpr S32 ce_factorial(S32 n)
+{
+	if (n<=0)
+	{
+		return 1;
+	}
+	else
+	{
+		return n*ce_factorial(n-1);
+	}
+}
+
+template<> template<>
+void cpp_features_test_object_t::test<9>()
+{
+	S32 val = compute2();
+	ensure("constexpr 1", val==2);
+
+	// Compile-time factorial. You used to need complex templates to do something this useless.
+	S32 fac5 = ce_factorial(5);
+	ensure("constexpr 2", fac5==120);
+}
+
+// static assert
+//
+// https://en.cppreference.com/w/cpp/language/static_assert
+//
+// You can add asserts to be checked at compile time. The thing to be checked must be a constexpr.
+// There are two forms:
+// * static_assert(expr);
+// * static_assert(expr, message);
+//
+// Currently only the 2-parameter form works on windows. The 1-parameter form needs a flag we don't set.
+
+template<> template<>
+void cpp_features_test_object_t::test<10>()
+{
+	// static_assert(ce_factorial(6)==720); No, needs a flag we don't currently set.
+	static_assert(ce_factorial(6)==720, "bad factorial"); // OK
+}
+
+
 
 } // namespace tut
-- 
cgit v1.2.3


From 7844f7e922cc28cb2b44c21f08039b44025eac0e Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 18 Mar 2021 16:57:48 +0200
Subject: SL-13910 Failed to upload image to your Profile Feed

Looks like viewer is missing some certs in the bundle or doesn't know how to handle web page's certs. For now disabling verification to not block DRTVWR-516. Verification was originally turned on in DRTVWR-516's SL-13927
---
 indra/newview/llviewermedia.cpp | 1 +
 indra/newview/llwebprofile.cpp  | 1 +
 2 files changed, 2 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 9ed2df2759..73d0a83a0d 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1237,6 +1237,7 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
     
     httpOpts->setFollowRedirects(true);
     httpOpts->setWantHeaders(true);
+    httpOpts->setSSLVerifyPeer(false); // viewer's cert bundle doesn't appear to agree with web certs from "https://my.secondlife.com/"
 
     LLURL hostUrl(url.c_str());
     std::string hostAuth = hostUrl.getAuthority();
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index 569f479a16..ff899fe895 100644
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -113,6 +113,7 @@ void LLWebProfile::uploadImageCoro(LLPointer<LLImageFormatted> image, std::strin
 
     httpOpts->setWantHeaders(true);
     httpOpts->setFollowRedirects(false);
+    httpOpts->setSSLVerifyPeer(false); ; // viewer's cert bundle doesn't appear to agree with web certs from "https://my.secondlife.com/"
 
     // Get upload configuration data.
     std::string configUrl(getProfileURL(std::string()) + "snapshots/s3_upload_config");
-- 
cgit v1.2.3


From c0f28ae36261cc31d6412c42c05d1b7719a2c04b Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 18 Mar 2021 22:45:38 +0200
Subject: SL-14927 Some avatar names not resolving

---
 indra/newview/llagent.cpp        | 15 +++++++--------
 indra/newview/llagent.h          |  2 +-
 indra/newview/llappviewer.cpp    |  7 +++----
 indra/newview/llappviewer.h      |  3 ++-
 indra/newview/llenvironment.cpp  |  2 +-
 indra/newview/llviewerregion.cpp |  4 ++--
 indra/newview/llviewerregion.h   |  2 +-
 indra/newview/llwlhandlers.cpp   |  2 +-
 8 files changed, 18 insertions(+), 19 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 5c00cfc783..baf0acc94b 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -879,13 +879,12 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal
 }
 
 // static
-void LLAgent::capabilityReceivedCallback(const LLUUID &region_id)
+void LLAgent::capabilityReceivedCallback(const LLUUID &region_id, LLViewerRegion *regionp)
 {
-    LLViewerRegion* region = gAgent.getRegion();
-    if (region && region->getRegionID() == region_id)
+    if (regionp && regionp->getRegionID() == region_id)
     {
-        region->requestSimulatorFeatures();
-        LLAppViewer::instance()->updateNameLookupUrl();
+        regionp->requestSimulatorFeatures();
+        LLAppViewer::instance()->updateNameLookupUrl(regionp);
     }
 }
 
@@ -936,7 +935,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
             if (regionp->capabilitiesReceived())
             {
                 regionp->requestSimulatorFeatures();
-                LLAppViewer::instance()->updateNameLookupUrl();
+                LLAppViewer::instance()->updateNameLookupUrl(regionp);
             }
             else
             {
@@ -962,11 +961,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
 
             if (regionp->capabilitiesReceived())
             {
-                LLAppViewer::instance()->updateNameLookupUrl();
+                LLAppViewer::instance()->updateNameLookupUrl(regionp);
             }
             else
             {
-                regionp->setCapabilitiesReceivedCallback([](const LLUUID &region_id) {LLAppViewer::instance()->updateNameLookupUrl(); });
+                regionp->setCapabilitiesReceivedCallback([](const LLUUID &region_id, LLViewerRegion* regionp) {LLAppViewer::instance()->updateNameLookupUrl(regionp); });
             }
 		}
 
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index d46c99db8c..f5ca42af5b 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -254,7 +254,7 @@ public:
 	boost::signals2::connection     addParcelChangedCallback(parcel_changed_callback_t);
 
 private:
-	static void capabilityReceivedCallback(const LLUUID &region_id);
+	static void capabilityReceivedCallback(const LLUUID &region_id, LLViewerRegion *regionp);
 
 	typedef boost::signals2::signal<void()> parcel_changed_signal_t;
 	parcel_changed_signal_t		mParcelChangedSignal;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 7c2f622abd..fe2da2f989 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -5226,10 +5226,9 @@ void LLAppViewer::sendLogoutRequest()
 	}
 }
 
-void LLAppViewer::updateNameLookupUrl()
+void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp)
 {
-    LLViewerRegion* region = gAgent.getRegion();
-    if (!region || !region->capabilitiesReceived())
+    if (!regionp || !regionp->capabilitiesReceived())
     {
         return;
     }
@@ -5238,7 +5237,7 @@ void LLAppViewer::updateNameLookupUrl()
     bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL();
     std::string name_lookup_url;
     name_lookup_url.reserve(128); // avoid a memory allocation below
-    name_lookup_url = region->getCapability("GetDisplayNames");
+    name_lookup_url = regionp->getCapability("GetDisplayNames");
     bool have_capability = !name_lookup_url.empty();
     if (have_capability)
     {
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 6db45583eb..95e93be572 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -57,6 +57,7 @@ class LLImageDecodeThread;
 class LLTextureFetch;
 class LLWatchdogTimeout;
 class LLViewerJoystick;
+class LLViewerRegion;
 
 extern LLTrace::BlockTimerStatHandle FTM_FRAME;
 
@@ -209,7 +210,7 @@ public:
 	// llcorehttp init/shutdown/config information.
 	LLAppCoreHttp & getAppCoreHttp()			{ return mAppCoreHttp; }
 
-    void updateNameLookupUrl();
+    void updateNameLookupUrl(const LLViewerRegion* regionp);
 
 protected:
 	virtual bool initWindow(); // Initialize the viewer's window.
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index b6f120e644..431ca4fc05 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1029,7 +1029,7 @@ void LLEnvironment::onRegionChange()
     }
     if (!cur_region->capabilitiesReceived())
     {
-        cur_region->setCapabilitiesReceivedCallback([](const LLUUID &region_id) {  LLEnvironment::instance().requestRegion(); });
+        cur_region->setCapabilitiesReceivedCallback([](const LLUUID &region_id, LLViewerRegion* regionp) {  LLEnvironment::instance().requestRegion(); });
         return;
     }
     requestRegion();
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 2fde4fe49c..f007aefc70 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2241,7 +2241,7 @@ void LLViewerRegion::setSimulatorFeaturesReceived(bool received)
 	mSimulatorFeaturesReceived = received;
 	if (received)
 	{
-		mSimulatorFeaturesReceivedSignal(getRegionID());
+		mSimulatorFeaturesReceivedSignal(getRegionID(), this);
 		mSimulatorFeaturesReceivedSignal.disconnect_all_slots();
 	}
 }
@@ -3183,7 +3183,7 @@ void LLViewerRegion::setCapabilitiesReceived(bool received)
 	// so that they can safely use getCapability().
 	if (received)
 	{
-		mCapabilitiesReceivedSignal(getRegionID());
+		mCapabilitiesReceivedSignal(getRegionID(), this);
 
 		LLFloaterPermsDefault::sendInitialPerms();
 
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index dfd8c64f76..fcbf56c81f 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -94,7 +94,7 @@ public:
 		NUM_PARTITIONS
 	} eObjectPartitions;
 
-	typedef boost::signals2::signal<void(const LLUUID& region_id)> caps_received_signal_t;
+	typedef boost::signals2::signal<void(const LLUUID& region_id, LLViewerRegion* regionp)> caps_received_signal_t;
 
 	LLViewerRegion(const U64 &handle,
 				   const LLHost &host,
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index 730aa3774f..d55e1b7cd3 100644
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -51,7 +51,7 @@ bool LLEnvironmentRequest::initiate(LLEnvironment::environment_apply_fn cb)
 	if (!cur_region->capabilitiesReceived())
 	{
 		LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL;
-        cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID &region_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); });
+        cur_region->setCapabilitiesReceivedCallback([cb](const LLUUID &region_id, LLViewerRegion* regionp) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); });
 		return false;
 	}
 
-- 
cgit v1.2.3


From a66932a091bac4d4ca1a861901b9cef619a406f7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 19 Mar 2021 12:55:04 +0200
Subject: SL-14927 Some avatar names not resolving in chat

buildConversationViewParticipant() was deparenting view models that belong to session
---
 indra/llui/llfolderviewitem.cpp | 10 ++++++++--
 indra/llui/llfolderviewitem.h   |  2 +-
 indra/llui/llfolderviewmodel.h  |  6 ++++--
 3 files changed, 13 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 9f6ceac768..31202f02bf 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -1608,7 +1608,7 @@ void LLFolderViewFolder::destroyView()
 
 // extractItem() removes the specified item from the folder, but
 // doesn't delete it.
-void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
+void LLFolderViewFolder::extractItem( LLFolderViewItem* item)
 {
 	if (item->isSelected())
 		getRoot()->clearSelection();
@@ -1631,7 +1631,13 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
 		mItems.erase(it);
 	}
 	//item has been removed, need to update filter
-	getViewModelItem()->removeChild(item->getViewModelItem());
+    LLFolderViewModelItem* parent_model = getViewModelItem();
+    LLFolderViewModelItem* child_model = item->getViewModelItem();
+    if (child_model->getParent() == parent_model)
+    {
+        // in some cases model does not belong to parent view, is shared between views
+        parent_model->removeChild(child_model);
+    }
 	//because an item is going away regardless of filter status, force rearrange
 	requestArrange();
 	removeChild(item);
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index da09d139e9..3bfc7ee8cf 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -387,7 +387,7 @@ public:
 
 	// extractItem() removes the specified item from the folder, but
 	// doesn't delete it.
-	virtual void extractItem( LLFolderViewItem* item );
+	virtual void extractItem( LLFolderViewItem* item);
 
 	// This function is called by a child that needs to be resorted.
 	void resort(LLFolderViewItem* item);
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index f4ddfa8f18..8684c71672 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -218,7 +218,8 @@ public:
 	virtual S32 getSortVersion() = 0;
 	virtual void setSortVersion(S32 version) = 0;
 	virtual void setParent(LLFolderViewModelItem* parent) = 0;
-	virtual bool hasParent() = 0;
+    virtual LLFolderViewModelItem* getParent() const = 0;
+	virtual bool hasParent() const = 0;
 
 protected:
 
@@ -358,7 +359,8 @@ public:
 
 protected:
 	virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; }
-	virtual bool hasParent() { return mParent != NULL; }
+    virtual LLFolderViewModelItem* getParent() const { return mParent; }
+	virtual bool hasParent() const { return mParent != NULL; }
 
 	S32							mSortVersion;
 	bool						mPassedFilter;
-- 
cgit v1.2.3


From 5f6a025397d0bcca27adc01fcb6fc324b7bdbd4d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 19 Mar 2021 13:40:19 +0200
Subject: Revert "SL-14927 Some avatar names not resolving in chat"

This reverts commit a66932a091bac4d4ca1a861901b9cef619a406f7.
---
 indra/llui/llfolderviewitem.cpp | 10 ++--------
 indra/llui/llfolderviewitem.h   |  2 +-
 indra/llui/llfolderviewmodel.h  |  6 ++----
 3 files changed, 5 insertions(+), 13 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 31202f02bf..9f6ceac768 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -1608,7 +1608,7 @@ void LLFolderViewFolder::destroyView()
 
 // extractItem() removes the specified item from the folder, but
 // doesn't delete it.
-void LLFolderViewFolder::extractItem( LLFolderViewItem* item)
+void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
 {
 	if (item->isSelected())
 		getRoot()->clearSelection();
@@ -1631,13 +1631,7 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item)
 		mItems.erase(it);
 	}
 	//item has been removed, need to update filter
-    LLFolderViewModelItem* parent_model = getViewModelItem();
-    LLFolderViewModelItem* child_model = item->getViewModelItem();
-    if (child_model->getParent() == parent_model)
-    {
-        // in some cases model does not belong to parent view, is shared between views
-        parent_model->removeChild(child_model);
-    }
+	getViewModelItem()->removeChild(item->getViewModelItem());
 	//because an item is going away regardless of filter status, force rearrange
 	requestArrange();
 	removeChild(item);
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 3bfc7ee8cf..da09d139e9 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -387,7 +387,7 @@ public:
 
 	// extractItem() removes the specified item from the folder, but
 	// doesn't delete it.
-	virtual void extractItem( LLFolderViewItem* item);
+	virtual void extractItem( LLFolderViewItem* item );
 
 	// This function is called by a child that needs to be resorted.
 	void resort(LLFolderViewItem* item);
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 8684c71672..f4ddfa8f18 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -218,8 +218,7 @@ public:
 	virtual S32 getSortVersion() = 0;
 	virtual void setSortVersion(S32 version) = 0;
 	virtual void setParent(LLFolderViewModelItem* parent) = 0;
-    virtual LLFolderViewModelItem* getParent() const = 0;
-	virtual bool hasParent() const = 0;
+	virtual bool hasParent() = 0;
 
 protected:
 
@@ -359,8 +358,7 @@ public:
 
 protected:
 	virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; }
-    virtual LLFolderViewModelItem* getParent() const { return mParent; }
-	virtual bool hasParent() const { return mParent != NULL; }
+	virtual bool hasParent() { return mParent != NULL; }
 
 	S32							mSortVersion;
 	bool						mPassedFilter;
-- 
cgit v1.2.3


From 65352e988410d8001d485fa9d72858e21cc80df7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 19 Mar 2021 13:47:32 +0200
Subject: SL-14927 Some avatar names not resolving in chat

---
 indra/llui/llfolderviewitem.cpp         | 8 ++++++--
 indra/llui/llfolderviewitem.h           | 2 +-
 indra/newview/llfloaterimsessiontab.cpp | 2 +-
 3 files changed, 8 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 9f6ceac768..285bf9f484 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -1608,7 +1608,7 @@ void LLFolderViewFolder::destroyView()
 
 // extractItem() removes the specified item from the folder, but
 // doesn't delete it.
-void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
+void LLFolderViewFolder::extractItem( LLFolderViewItem* item, bool deparent_model )
 {
 	if (item->isSelected())
 		getRoot()->clearSelection();
@@ -1631,7 +1631,11 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item )
 		mItems.erase(it);
 	}
 	//item has been removed, need to update filter
-	getViewModelItem()->removeChild(item->getViewModelItem());
+    if (deparent_model)
+    {
+        // in some cases model does not belong to parent view, is shared between views
+        getViewModelItem()->removeChild(item->getViewModelItem());
+    }
 	//because an item is going away regardless of filter status, force rearrange
 	requestArrange();
 	removeChild(item);
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index da09d139e9..616d2e7d86 100644
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -387,7 +387,7 @@ public:
 
 	// extractItem() removes the specified item from the folder, but
 	// doesn't delete it.
-	virtual void extractItem( LLFolderViewItem* item );
+	virtual void extractItem( LLFolderViewItem* item, bool deparent_model = true);
 
 	// This function is called by a child that needs to be resorted.
 	void resort(LLFolderViewItem* item);
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 80165f9b9a..ed1d7a81cc 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -532,7 +532,7 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
 	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
 	if (widget)
 	{
-		mConversationsRoot->extractItem(widget);
+		mConversationsRoot->extractItem(widget, false);
 		delete widget;
 	}
 	mConversationsWidgets.erase(participant_id);
-- 
cgit v1.2.3


From 026f4c6024ced642e7fff1949a38657b40a92c45 Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Fri, 26 Mar 2021 14:41:58 +0100
Subject: SL-14999 - more cpp features tests

---
 indra/newview/tests/cppfeatures_test.cpp | 43 ++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index bfaa83140d..9f052c11c4 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -335,6 +335,49 @@ void cpp_features_test_object_t::test<10>()
 	static_assert(ce_factorial(6)==720, "bad factorial"); // OK
 }
 
+// type aliases
+//
+// https://en.cppreference.com/w/cpp/language/type_alias
+// 
+// You can use the "using" statement to create simpler templates that
+// are aliases for more complex ones. "Template typedef"
+
+// This makes stringmap<T> an alias for std::map<std::string, T>
+template<typename T>
+using stringmap = std::map<std::string, T>;
+
+template<> template<>
+void cpp_features_test_object_t::test<11>()
+{
+	stringmap<S32> name_counts{ {"alice", 3}, {"bob", 2} };
+	ensure("type alias", name_counts["bob"]==2);
+}
+
+
+// nullptr
+
+// enums
+
+// std::unique_ptr and make_unique
+
+// std::shared_ptr and make_shared
+
+// lambdas
+
+// perfect forwarding
+
+// variadic templates
+
+// std::thread
+
+// std::mutex
+
+// thread_local
+
+// rvalue reference &&
+
+// move semantics
 
+// std::move
 
 } // namespace tut
-- 
cgit v1.2.3


From 9013a04eddc9631c5040d50ad766e5708801dcab Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 1 Apr 2021 16:51:27 +0100
Subject: SL-14999 - note

---
 indra/newview/tests/cppfeatures_test.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/tests/cppfeatures_test.cpp b/indra/newview/tests/cppfeatures_test.cpp
index 9f052c11c4..923bb1e1b2 100644
--- a/indra/newview/tests/cppfeatures_test.cpp
+++ b/indra/newview/tests/cppfeatures_test.cpp
@@ -353,10 +353,11 @@ void cpp_features_test_object_t::test<11>()
 	ensure("type alias", name_counts["bob"]==2);
 }
 
+// Other possibilities:
 
 // nullptr
 
-// enums
+// class enums
 
 // std::unique_ptr and make_unique
 
@@ -380,4 +381,6 @@ void cpp_features_test_object_t::test<11>()
 
 // std::move
 
+// string_view
+
 } // namespace tut
-- 
cgit v1.2.3


From 1dfbce8169dbb9916723031e23a80548d9c496c3 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 8 Apr 2021 16:17:00 +0300
Subject: SL-15082 fix for app/region SLURLS

---
 indra/llui/llurlentry.cpp        |  2 +-
 indra/newview/llviewerregion.cpp | 11 ++++++++++-
 2 files changed, 11 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 7250e6ca7e..06e7070f7e 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -1103,7 +1103,7 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
 //
 LLUrlEntryRegion::LLUrlEntryRegion()
 {
-	mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
+	mPattern = boost::regex("secondlife:///app/region/[A-Za-z0-9]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_slurl.xml";
 	mTooltip = LLTrans::getString("TooltipSLURL");
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f007aefc70..359930b2cd 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -82,6 +82,8 @@
 #include "llcallstack.h"
 #include "llsettingsdaycycle.h"
 
+#include <boost/regex.hpp>
+
 #ifdef LL_WINDOWS
 	#pragma warning(disable:4355)
 #endif
@@ -143,15 +145,22 @@ public:
            
         // build a secondlife://{PLACE} SLurl from this SLapp
         std::string url = "secondlife://";
+		boost::regex name_rx("[A-Za-z0-9]+");
+		boost::regex coord_rx("[0-9]+");
         for (int i = 0; i < num_params; i++)
         {
             if (i > 0)
             {
                 url += "/";
             }
+			if (!boost::regex_match(params[i].asString(), i > 0 ? coord_rx : name_rx))
+			{
+				return false;
+			}
+
             url += params[i].asString();
         }
-           
+
         // Process the SLapp as if it was a secondlife://{PLACE} SLurl
         LLURLDispatcher::dispatch(url, "clicked", web, true);
         return true;
-- 
cgit v1.2.3


From 0ad34bfb26aa1c14ab854dc6a86f8c0ea5f8ae51 Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Fri, 9 Apr 2021 19:23:34 +0300
Subject: =?UTF-8?q?SL-15094=20FIXED=20=E2=80=98My=20last=20location?=
 =?UTF-8?q?=E2=80=99=20is=20used=20instead=20of=20entered=20location?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 indra/newview/llpanellogin.cpp | 15 +++++++++------
 indra/newview/llpanellogin.h   |  2 +-
 2 files changed, 10 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 0e7634f1d2..d7462f50e2 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -254,7 +254,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
 	LLLineEditor* password_edit(getChild<LLLineEditor>("password_edit"));
 	password_edit->setKeystrokeCallback(onPassKey, this);
 	// STEAM-14: When user presses Enter with this field in focus, initiate login
-	password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+	password_edit->setCommitCallback(boost::bind(&LLPanelLogin::onClickConnect, false));
 
 	// change z sort of clickable text to be behind buttons
 	sendChildToBack(getChildView("forgot_password_text"));
@@ -265,7 +265,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
     {
         LLComboBox* favorites_combo = getChild<LLComboBox>("start_location_combo");
         updateLocationSelectorsVisibility(); // separate so that it can be called from preferences
-        favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, this));
+        favorites_combo->setReturnCallback(boost::bind(&LLPanelLogin::onClickConnect, false));
         favorites_combo->setFocusLostCallback(boost::bind(&LLPanelLogin::onLocationSLURL, this));
 
         LLComboBox* server_choice_combo = getChild<LLComboBox>("server_combo");
@@ -997,12 +997,15 @@ void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
 // Protected methods
 //---------------------------------------------------------------------------
 // static
-void LLPanelLogin::onClickConnect(void *)
+void LLPanelLogin::onClickConnect(bool commit_fields)
 {
 	if (sInstance && sInstance->mCallback)
 	{
-		// JC - Make sure the fields all get committed.
-		sInstance->setFocus(FALSE);
+		if (commit_fields)
+		{
+			// JC - Make sure the fields all get committed.
+			sInstance->setFocus(FALSE);
+		}
 
 		LLComboBox* combo = sInstance->getChild<LLComboBox>("server_combo");
 		LLSD combo_val = combo->getSelectedValue();
@@ -1125,7 +1128,7 @@ void LLPanelLogin::onUserListCommit(void*)
            }
            else
            {
-               onClickConnect(NULL);
+               onClickConnect();
            }
         }
     }
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index c9b8e1b6fc..5871cae059 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -98,7 +98,7 @@ private:
 
 	static void setFields(LLPointer<LLCredential> credential);
 
-	static void onClickConnect(void*);
+	static void onClickConnect(bool commit_fields = true);
 	static void onClickNewAccount(void*);
 	static void onClickVersion(void*);
 	static void onClickForgotPassword(void*);
-- 
cgit v1.2.3


From 94ce45441d3e00a8ff2dac6c41be23fa04cee31b Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Sat, 10 Apr 2021 01:38:17 +0300
Subject: SL-15082 regexp fix

---
 indra/llui/llurlentry.cpp            | 2 +-
 indra/llui/tests/llurlentry_test.cpp | 5 -----
 indra/newview/llviewerregion.cpp     | 2 +-
 3 files changed, 2 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 06e7070f7e..6ff1b0764e 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -1103,7 +1103,7 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
 //
 LLUrlEntryRegion::LLUrlEntryRegion()
 {
-	mPattern = boost::regex("secondlife:///app/region/[A-Za-z0-9]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
+	mPattern = boost::regex("secondlife:///app/region/[A-Za-z0-9()_%]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
 							boost::regex::perl|boost::regex::icase);
 	mMenuName = "menu_url_slurl.xml";
 	mTooltip = LLTrans::getString("TooltipSLURL");
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 4a4fdb72e3..1a474cca90 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -739,11 +739,6 @@ namespace tut
 				  "XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",
 				  "secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30");
 
-		// DEV-35459: SLURLs and teleport Links not parsed properly
-		testRegex("Region with quote", url,
-				  "XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX",
-			          "secondlife:///app/region/A%27ksha%20Oasis/41/166/701");
-
 		// Rendering tests.
 		testLabel("Render /app/region/Ahern/50/50/50/", url,
 			"secondlife:///app/region/Ahern/50/50/50/",
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 359930b2cd..7628a6c7ef 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -145,7 +145,7 @@ public:
            
         // build a secondlife://{PLACE} SLurl from this SLapp
         std::string url = "secondlife://";
-		boost::regex name_rx("[A-Za-z0-9]+");
+		boost::regex name_rx("[A-Za-z0-9()_%]+");
 		boost::regex coord_rx("[0-9]+");
         for (int i = 0; i < num_params; i++)
         {
-- 
cgit v1.2.3


From 33b30fd7e0e5bc2c8e0e737402c3e19675a53c3f Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 14 Apr 2021 22:01:23 +0300
Subject: SL-15077 Mac Crash destroying LLNotificationSet

Not a fix. Mac sometimes crashes when destroying mItems in LLPersistentNotificationChannel
Decided to try cleaning mItems explicitly to see if it will change callstack, it won't fix the crash, but will help figuring out if source of the issue is in mItems or is LLPersistentNotificationChannel itself
---
 indra/llui/llnotificationptr.h |  3 +--
 indra/llui/llnotifications.h   | 15 +++++++++++----
 indra/newview/llmediactrl.h    |  3 ++-
 3 files changed, 14 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h
index acc047527f..580f353c7d 100644
--- a/indra/llui/llnotificationptr.h
+++ b/indra/llui/llnotificationptr.h
@@ -27,9 +27,8 @@
 
 // Many classes just store a single LLNotificationPtr
 // and llnotifications.h is very large, so define this ligher header.
-#include <boost/shared_ptr.hpp>
 
 class LLNotification;
-typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
+typedef std::shared_ptr<LLNotification> LLNotificationPtr;
 
 #endif
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 2f4578da17..39576ad86d 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -85,7 +85,6 @@
 
 #include <boost/utility.hpp>
 #include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
 #include <boost/type_traits.hpp>
 #include <boost/signals2.hpp>
 #include <boost/range.hpp>
@@ -304,7 +303,7 @@ typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibility
  */
 class LLNotification  : 
 	boost::noncopyable,
-	public boost::enable_shared_from_this<LLNotification>
+	public std::enable_shared_from_this<LLNotification>
 {
 LOG_CLASS(LLNotification);
 friend class LLNotifications;
@@ -743,7 +742,10 @@ public:
 	:	mFilter(filter), 
 		mItems() 
 	{}
-	virtual ~LLNotificationChannelBase() {}
+    virtual ~LLNotificationChannelBase()
+    {
+        mItems.clear();
+    }
 	// you can also connect to a Channel, so you can be notified of
 	// changes to this channel
     LLBoundListener connectChanged(const LLEventListener& slot)
@@ -873,6 +875,7 @@ class LLNotifications :
 {
 	LLSINGLETON(LLNotifications);
 	LOG_CLASS(LLNotifications);
+	virtual ~LLNotifications() {}
 
 public:
 
@@ -1070,7 +1073,11 @@ public:
 	LLPersistentNotificationChannel() 
 		:	LLNotificationChannel("Persistent", "Visible", &notificationFilter)
 	{}
-	virtual ~LLPersistentNotificationChannel() {}
+
+    virtual ~LLPersistentNotificationChannel()
+    {
+        mHistory.clear();
+    }
 
 	typedef std::vector<LLNotificationPtr> history_list_t;
 	history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); }
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 958c76f261..bd24c47a4f 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -31,6 +31,7 @@
 
 #include "lluictrl.h"
 #include "llframetimer.h"
+#include "llnotificationptr.h"
 
 class LLViewBorder;
 class LLUICtrlFactory;
@@ -145,7 +146,7 @@ public:
 
 		void setTextureSize(S32 width, S32 height);
 
-		void showNotification(boost::shared_ptr<class LLNotification> notify);
+		void showNotification(LLNotificationPtr notify);
 		void hideNotification();
 
 		void setTrustedContent(bool trusted);
-- 
cgit v1.2.3


From 56eda0385e91d6ede51f874321bbd8ebfd293c2f Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 16 Apr 2021 20:37:02 +0300
Subject: SL-13395 Allow creating outfit folders under My Outfits

---
 indra/newview/llinventorybridge.cpp                   | 9 ++++++++-
 indra/newview/skins/default/xui/en/menu_inventory.xml | 8 ++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index d35d8456be..a729b276d5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -3987,6 +3987,12 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 	const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 	const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
 	const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+	const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false);
+
+	if (outfits_id == mUUID)
+	{
+		items.push_back(std::string("New Outfit"));
+	}
 
 	if (lost_and_found_id == mUUID)
 	{
@@ -4085,7 +4091,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		// Not sure what the right thing is to do here.
 		if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
 		{
-			if (!isInboxFolder()) // don't allow creation in inbox
+			if (!isInboxFolder() // don't allow creation in inbox
+				&& outfits_id != mUUID)
 			{
 				// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
 				if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index eda9739976..5a35bbf121 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -151,6 +151,14 @@
          function="Inventory.DoCreate"
          parameter="category" />
     </menu_item_call>
+    <menu_item_call
+     label="New Outfit"
+     layout="topleft"
+     name="New Outfit">
+        <menu_item_call.on_click
+         function="Inventory.DoCreate"
+         parameter="outfit" />
+    </menu_item_call>
     <menu_item_call
      label="New Script"
      layout="topleft"
-- 
cgit v1.2.3


From 6e7b0fc8823118127b3d182bbe13c43304f918b1 Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Tue, 20 Apr 2021 15:52:00 -0700
Subject: SL-15072: First part of adding ability to disable the VIVOX auto VAD
 feature and set our own values via Debug Settings - hardcoded currently for
 testing but will be pulled from global settings eventually

---
 indra/newview/llvoicevivox.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++
 indra/newview/llvoicevivox.h   |  2 ++
 2 files changed, 67 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index a8d668420e..39d6868b5c 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -1883,6 +1883,13 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
     notifyParticipantObservers();
     notifyVoiceFontObservers();
 
+	// disable the automatic VAD and explicitly set the VAD variables ourselves
+	// see SL-15072 for more details
+	unsigned int vad_hangover = 2001;
+	unsigned int vad_noise_floor = 577;
+	unsigned int vad_sensitivity = 44;
+	setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
+
     LLSD timeoutEvent(LLSDMap("timeout", LLSD::Boolean(true)));
 
     mIsInChannel = true;
@@ -3217,6 +3224,56 @@ void LLVivoxVoiceClient::sendLocalAudioUpdates()
 	}
 }
 
+/**
+ * Because of the recurring voice cutout issues (SL-15072) we are going to try
+ * to disable the automatic VAD (Voice Activity Detection) and set the associated
+ * parameters directly. We will expose them via Debug Settings and that should
+ * let us iterate on a collection of values that work for us. Hopefully! 
+ *
+ * From the VIVOX Docs:
+ *
+ * vad_hangover: The 'Hangover time' - the time (in milliseconds) that it takes
+ * for the VAD to switch back to silence from speech mode after the last speech
+ * frame has been detected.
+ *
+ * vad_noise_floor: The 'vad noise floor' - A dimensionless value between 0 and 
+ * 20000 (default 576) that controls the maximum level at which the noise floor
+ * may be set at by the VAD's noise tracking. Too low of a value will make noise
+ * tracking ineffective (A value of 0 disables noise tracking and the VAD then 
+ * relies purely on the sensitivity property). Too high of a value will make 
+ * long speech classifiable as noise.
+ *
+ * vad_sensitivity: The 'vad sensitivity' - A dimensionless value between 0 and 
+ * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds
+ * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive, 
+ * while 100 is 'least sensitive')
+ */
+void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover,
+                                        unsigned int vad_noise_floor,
+                                        unsigned int vad_sensitivity)
+{
+    std::ostringstream stream;
+
+    // explicitly turn off the automatic VAD even though the
+    // default state is also disabled.
+    const unsigned int vad_auto_enabled = 0;
+
+    // Create a request to set the VAD parameters:
+    LL_INFOS("Voice") << "Disabling the automatic VAD and setting the parameters explicitly." << LL_ENDL;
+
+    stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
+               << "<VadAuto>" << vad_auto_enabled << "</VadAuto>"
+               << "<VadHangover>" << vad_hangover << "</VadHangover>"
+               << "<vad_noise_floor>" << vad_hangover << "</vad_noise_floor>"
+               << "<vad_sensitivity>" << vad_hangover << "</vad_sensitivity>"
+           << "</Request>\n\n\n";
+
+    if (!stream.str().empty())
+    {
+        writeString(stream.str());
+    }
+}
+
 /////////////////////////////
 // Response/Event handlers
 
@@ -7569,6 +7626,14 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		{
 			LLVivoxVoiceClient::getInstance()->accountGetTemplateFontsResponse(statusCode, statusString);
 		}
+		else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
+		{
+			std::cout << "@@@----" << std::endl;
+			std::cout << "    Response for Aux.SetVadProperties.1 was" << std::endl;
+			std::cout << "      statusCode: " << statusCode << std::endl;
+			std::cout << "    statusString: " << statusString << std::endl;
+			std::cout << "----@@@" << std::endl;
+		}
 		/*
 		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
 		 {
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 699c85066b..7985eae6e4 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -446,6 +446,8 @@ protected:
 	// local audio updates, mic mute, speaker mute, mic volume and speaker volumes
 	void sendLocalAudioUpdates();
 
+	// disable auto-VAD and configure VAD parameters explicitly
+    void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
 
 	/////////////////////////////
 	// Response/Event handlers
-- 
cgit v1.2.3


From 28935a8b6435eaf41ab13605097257c9d7f5afda Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Tue, 20 Apr 2021 16:28:58 -0700
Subject: Move location where we call function to setup VAD but didn't help

---
 indra/newview/llvoicevivox.cpp | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 39d6868b5c..fa4504de62 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -683,7 +683,14 @@ void LLVivoxVoiceClient::voiceControlCoro()
         bool success = startAndConnectSession();
         if (success)
         {
-            if (mTuningMode)
+			// disable the automatic VAD and explicitly set the VAD variables ourselves
+			// see SL-15072 for more details
+			unsigned int vad_hangover = 2001;
+			unsigned int vad_noise_floor = 577;
+			unsigned int vad_sensitivity = 44;
+			setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
+			
+			if (mTuningMode)
             {
                 performMicTuning();
             }
@@ -1883,13 +1890,6 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
     notifyParticipantObservers();
     notifyVoiceFontObservers();
 
-	// disable the automatic VAD and explicitly set the VAD variables ourselves
-	// see SL-15072 for more details
-	unsigned int vad_hangover = 2001;
-	unsigned int vad_noise_floor = 577;
-	unsigned int vad_sensitivity = 44;
-	setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
-
     LLSD timeoutEvent(LLSDMap("timeout", LLSD::Boolean(true)));
 
     mIsInChannel = true;
@@ -7628,11 +7628,13 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		}
 		else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
 		{
-			std::cout << "@@@----" << std::endl;
+			// temporary for debugging- will eventually remove entirely or replace with a 
+			// toast message to alert the user that it was set
+			std::cout << "@@@" << std::endl;
 			std::cout << "    Response for Aux.SetVadProperties.1 was" << std::endl;
-			std::cout << "      statusCode: " << statusCode << std::endl;
-			std::cout << "    statusString: " << statusString << std::endl;
-			std::cout << "----@@@" << std::endl;
+			std::cout << "          statusCode: " << statusCode << std::endl;
+			std::cout << "        statusString: " << statusString << std::endl;
+			std::cout << "@@@" << std::endl;
 		}
 		/*
 		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
-- 
cgit v1.2.3


From 766ba20028992a86547865e8228b33db3897c068 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 21 Apr 2021 18:27:04 +0300
Subject: SL-15152 Crashfix: Do not update environments when quiting

---
 indra/newview/llenvironment.cpp | 12 ++++++++++++
 1 file changed, 12 insertions(+)

(limited to 'indra')

diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 431ca4fc05..79f72220ed 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1992,6 +1992,10 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ
     {
         LL_WARNS("ENVIRONMENT") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
     }
+    else if (LLApp::isExiting())
+    {
+        return;
+    }
     else
     {
         LLSD environment = result[KEY_ENVIRONMENT];
@@ -2081,6 +2085,10 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf
         notify = LLSD::emptyMap();
         notify["FAIL_REASON"] = result["message"].asString();
     }
+    else if (LLApp::isExiting())
+    {
+        return;
+    }
     else
     {
         LLSD environment = result[KEY_ENVIRONMENT];
@@ -2143,6 +2151,10 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen
         notify = LLSD::emptyMap();
         notify["FAIL_REASON"] = result["message"].asString();
     }
+    else if (LLApp::isExiting())
+    {
+        return;
+    }
     else
     {
        LLSD environment = result[KEY_ENVIRONMENT];
-- 
cgit v1.2.3


From 5ef055fe69d64917ba1b40856ab02fc20036dffc Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Wed, 21 Apr 2021 12:07:18 -0700
Subject: SL-15072 update. Values for VAD settings now stored in debug
 settings. Request successfully sent at startup and also, whenever a relevant
 debug setting is changed. Going to send this build to Brett to test

---
 indra/newview/app_settings/settings.xml | 38 +++++++++++++++++++++++++-
 indra/newview/llvoicevivox.cpp          | 48 ++++++++++++++++++++++-----------
 indra/newview/llvoicevivox.h            |  9 ++++---
 3 files changed, 75 insertions(+), 20 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 626a3d1ff3..bedf8a7bfe 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14425,7 +14425,43 @@
       <key>Value</key>
       <integer>44125</integer>
     </map>
-    <key>VoiceCallsFriendsOnly</key>
+
+
+  <key>VivoxVadHangover</key>
+  <map>
+    <key>Comment</key>
+    <string>The time (in milliseconds) that it takes or the VAD to switch back to silence from speech mode after the last speech frame has been detected</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>2000</integer>
+  </map>
+  <key>VivoxVadNoiseFloor</key>
+  <map>
+    <key>Comment</key>
+    <string>A dimensionless value between 0 and 20000 (default 576) that controls the maximum level at which the noise floor may be set at by the VAD's noise tracking</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>576</integer>
+  </map>
+  <key>VivoxVadSensitivity</key>
+  <map>
+    <key>Comment</key>
+    <string>
+      A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>40</integer>
+  </map>
+  <key>VoiceCallsFriendsOnly</key>
     <map>
       <key>Comment</key>
       <string>(Deprecated) Only accept voice calls from residents on your friends list</string>
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index fa4504de62..f2115feb10 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -651,7 +651,6 @@ void LLVivoxVoiceClient::idle(void* user_data)
 {
 }
 
-
 //=========================================================================
 // the following are methods to support the coroutine implementation of the 
 // voice connection and processing.  They should only be called in the context 
@@ -683,13 +682,18 @@ void LLVivoxVoiceClient::voiceControlCoro()
         bool success = startAndConnectSession();
         if (success)
         {
-			// disable the automatic VAD and explicitly set the VAD variables ourselves
-			// see SL-15072 for more details
-			unsigned int vad_hangover = 2001;
-			unsigned int vad_noise_floor = 577;
-			unsigned int vad_sensitivity = 44;
+			// disable the automatic VAD and explicitly set the initial values of 
+			// the VAD variables ourselves see SL-15072 for more details
+			unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+			unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+			unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
 			setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
 			
+			// watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
+			gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+			gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+			gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+
 			if (mTuningMode)
             {
                 performMicTuning();
@@ -737,7 +741,6 @@ void LLVivoxVoiceClient::voiceControlCoro()
     LL_INFOS("Voice") << "exiting" << LL_ENDL;
 }
 
-
 bool LLVivoxVoiceClient::startAndConnectSession()
 {
     bool ok = false;
@@ -3264,8 +3267,8 @@ void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover,
     stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
                << "<VadAuto>" << vad_auto_enabled << "</VadAuto>"
                << "<VadHangover>" << vad_hangover << "</VadHangover>"
-               << "<vad_noise_floor>" << vad_hangover << "</vad_noise_floor>"
-               << "<vad_sensitivity>" << vad_hangover << "</vad_sensitivity>"
+               << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>"
+               << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>"
            << "</Request>\n\n\n";
 
     if (!stream.str().empty())
@@ -3274,6 +3277,17 @@ void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover,
     }
 }
 
+void LLVivoxVoiceClient::onVADSettingsChange()
+{
+	// pick up the VAD variables (one of which was changed)
+	unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+	unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+	unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+
+	// build a VAD params change request and send it to SLVoice
+	setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
+}
+
 /////////////////////////////
 // Response/Event handlers
 
@@ -7628,13 +7642,15 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
 		}
 		else if (!stricmp(actionCstr, "Aux.SetVadProperties.1"))
 		{
-			// temporary for debugging- will eventually remove entirely or replace with a 
-			// toast message to alert the user that it was set
-			std::cout << "@@@" << std::endl;
-			std::cout << "    Response for Aux.SetVadProperties.1 was" << std::endl;
-			std::cout << "          statusCode: " << statusCode << std::endl;
-			std::cout << "        statusString: " << statusString << std::endl;
-			std::cout << "@@@" << std::endl;
+			// both values of statusCode (old and more recent) indicate valid requests
+			if (statusCode != 0 && statusCode != 200)
+			{
+				LL_WARNS("Voice") << "Aux.SetVadProperties.1 request failed: "
+					<< "statusCode: " << statusCode
+					<< " and "
+					<< "statusString: " << statusString
+					<< LL_ENDL;
+			}
 		}
 		/*
 		 else if (!stricmp(actionCstr, "Account.ChannelGetList.1"))
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 7985eae6e4..960030659d 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -446,9 +446,6 @@ protected:
 	// local audio updates, mic mute, speaker mute, mic volume and speaker volumes
 	void sendLocalAudioUpdates();
 
-	// disable auto-VAD and configure VAD parameters explicitly
-    void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
-
 	/////////////////////////////
 	// Response/Event handlers
 	void connectorCreateResponse(int statusCode, std::string &statusString, std::string &connectorHandle, std::string &versionID);
@@ -474,6 +471,12 @@ protected:
 	
 	void muteListChanged();
 		
+	/////////////////////////////
+	// VAD changes
+	// disable auto-VAD and configure VAD parameters explicitly
+	void setupVADParams(unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
+	void onVADSettingsChange();
+
 	/////////////////////////////
 	// Sending updates of current state
 	void updatePosition(void);
-- 
cgit v1.2.3


From 1b900651f193c3750b51b9e945797e1f6d3c63f5 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 21 Apr 2021 22:36:24 +0300
Subject: SL-14956 Fix landmarks sometimes staying in mLoadedCallbackMap

---
 indra/newview/lllandmarklist.cpp | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 0a05ce6ab8..b88ef39a07 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -221,21 +221,15 @@ void LLLandmarkList::onRegionHandle(const LLUUID& landmark_id)
 {
 	LLLandmark* landmark = getAsset(landmark_id);
 
-	if (!landmark)
-	{
-		LL_WARNS() << "Got region handle but the landmark not found." << LL_ENDL;
-		return;
-	}
-
 	// Calculate landmark global position.
 	// This should succeed since the region handle is available.
 	LLVector3d pos;
-	if (!landmark->getGlobalPos(pos))
+	if (landmark && !landmark->getGlobalPos(pos))
 	{
-		LL_WARNS() << "Got region handle but the landmark global position is still unknown." << LL_ENDL;
-		return;
+		LL_WARNS() << "Got region handle but the landmark " << landmark_id << " global position is still unknown." << LL_ENDL;
 	}
 
+    // Call this even if no landmark exists to clean mLoadedCallbackMap
 	makeCallbacks(landmark_id);
 }
 
@@ -245,7 +239,7 @@ void LLLandmarkList::makeCallbacks(const LLUUID& landmark_id)
 
 	if (!landmark)
 	{
-		LL_WARNS() << "Landmark to make callbacks for not found." << LL_ENDL;
+		LL_WARNS() << "Landmark " << landmark_id << " to make callbacks for not found." << LL_ENDL;
 	}
 
 	// make all the callbacks here.
-- 
cgit v1.2.3


From be7f6b857547e008500b56a9838b5df72b0b49cd Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 23 Apr 2021 00:22:31 +0300
Subject: SL-14956 Fix landmarks sometimes staying in mLoadedCallbackMap #2

Improved fix
---
 indra/newview/lllandmarklist.cpp | 29 ++++++++++++++++++++++++++---
 indra/newview/lllandmarklist.h   |  1 +
 2 files changed, 27 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index b88ef39a07..88d3f2c5b6 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -162,6 +162,16 @@ void LLLandmarkList::processGetAssetReply(
                     gLandmarkList.makeCallbacks(uuid);
                 }
             }
+            else
+            {
+                // failed to parse, shouldn't happen
+                gLandmarkList.eraseCallbacks(uuid);
+            }
+        }
+        else
+        {
+            // got a good status, but no file, shouldn't happen
+            gLandmarkList.eraseCallbacks(uuid);
         }
 	}
 	else
@@ -180,7 +190,7 @@ void LLLandmarkList::processGetAssetReply(
 
 		gLandmarkList.mBadList.insert(uuid);
         gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests
-        // todo: this should clean mLoadedCallbackMap!
+        gLandmarkList.eraseCallbacks(uuid);
 	}
 
     // getAssetData can fire callback immediately, causing
@@ -220,19 +230,32 @@ BOOL LLLandmarkList::assetExists(const LLUUID& asset_uuid)
 void LLLandmarkList::onRegionHandle(const LLUUID& landmark_id)
 {
 	LLLandmark* landmark = getAsset(landmark_id);
+    if (!landmark)
+    {
+        LL_WARNS() << "Got region handle but the landmark " << landmark_id << " not found." << LL_ENDL;
+        eraseCallbacks(landmark_id);
+        return;
+    }
 
 	// Calculate landmark global position.
 	// This should succeed since the region handle is available.
 	LLVector3d pos;
-	if (landmark && !landmark->getGlobalPos(pos))
+	if (!landmark->getGlobalPos(pos))
 	{
-		LL_WARNS() << "Got region handle but the landmark " << landmark_id << " global position is still unknown." << LL_ENDL;
+        LL_WARNS() << "Got region handle but the landmark " << landmark_id << " global position is still unknown." << LL_ENDL;
+        eraseCallbacks(landmark_id);
+        return;
 	}
 
     // Call this even if no landmark exists to clean mLoadedCallbackMap
 	makeCallbacks(landmark_id);
 }
 
+void LLLandmarkList::eraseCallbacks(const LLUUID& landmark_id)
+{
+    mLoadedCallbackMap.erase(landmark_id);
+}
+
 void LLLandmarkList::makeCallbacks(const LLUUID& landmark_id)
 {
 	LLLandmark* landmark = getAsset(landmark_id);
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index 2e7bd25610..4f3b11660d 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -65,6 +65,7 @@ public:
 
 protected:
 	void onRegionHandle(const LLUUID& landmark_id);
+	void eraseCallbacks(const LLUUID& landmark_id);
 	void makeCallbacks(const LLUUID& landmark_id);
 
 	typedef std::map<LLUUID, LLLandmark*> landmark_list_t;
-- 
cgit v1.2.3


From d91f3ab6ae8e94a96c1173efad50015b721bee73 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Sat, 24 Apr 2021 01:00:21 +0300
Subject: SL-15150 Crash at LLScrollColumnHeader::updateResizeBars

Looks like mHeader is invalid yet mHeader->updateResizeBars() gets called, decided to validate column pointer
---
 indra/llui/llscrolllistcolumn.cpp | 4 ++--
 indra/llui/llscrolllistctrl.cpp   | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index cc9ff7a487..82b0415624 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -257,7 +257,7 @@ void LLScrollColumnHeader::updateResizeBars()
 	for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
 	{
 		LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
-		if (columnp->mHeader && columnp->mHeader->canResize())
+		if (columnp && columnp->mHeader && columnp->mHeader->canResize())
 		{
 			num_resizable_columns++;
 		}
@@ -269,7 +269,7 @@ void LLScrollColumnHeader::updateResizeBars()
 	for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
 	{
 		LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
-		if (!columnp->mHeader) continue;
+		if (!columnp || !columnp->mHeader) continue;
 		BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
 		columnp->mHeader->enableResizeBar(enable);
 		if (enable)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index be85f1cb6a..de644185fd 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -743,12 +743,12 @@ void LLScrollListCtrl::updateColumns(bool force_update)
 	LLScrollColumnHeader* last_header = NULL;
 	for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)
 	{
-		if ((*column_ordered_it)->getWidth() < 0)
+		LLScrollListColumn* column = *column_ordered_it;
+		if (!column || column->getWidth() < 0)
 		{
 			// skip hidden columns
 			continue;
 		}
-		LLScrollListColumn* column = *column_ordered_it;
 		
 		if (column->mHeader)
 		{
-- 
cgit v1.2.3


From 8ce21268a1723738aaded551812d71e5ec29c707 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 28 Apr 2021 19:46:56 +0300
Subject: SL-15181 Crash at LLSkinningUtil::initSkinningMatrixPalette

---
 indra/newview/llskinningutil.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp
index f325315933..e02b21f036 100644
--- a/indra/newview/llskinningutil.cpp
+++ b/indra/newview/llskinningutil.cpp
@@ -131,7 +131,12 @@ void LLSkinningUtil::initSkinningMatrixPalette(
     initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
     for (U32 j = 0; j < count; ++j)
     {
-        LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
+        S32 joint_num = skin->mJointNums[j];
+        LLJoint *joint = NULL;
+        if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)
+        {
+            joint = avatar->getJoint(joint_num);
+        }
         llassert(joint);
         if (joint)
         {
-- 
cgit v1.2.3


From 0ccb0306da93fa279909f45131009e80687f2f3d Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Wed, 28 Apr 2021 11:41:53 -0700
Subject: After a small but successful test at our standup, we're going to make
 the default value for the VAD sensitivity 0 (off).  The settings can all
 still be changed via Debug variables but this seems like a sensible starting
 point for the next test.

---
 indra/newview/app_settings/settings.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index bedf8a7bfe..5d2a678e7e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14453,13 +14453,13 @@
   <map>
     <key>Comment</key>
     <string>
-      A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD</string>
+      A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
     <string>U32</string>
     <key>Value</key>
-    <integer>40</integer>
+    <integer>0</integer>
   </map>
   <key>VoiceCallsFriendsOnly</key>
     <map>
-- 
cgit v1.2.3


From 0d793f4fa3b6687b51f0773296cb3dc06474c5ea Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 29 Apr 2021 21:13:21 +0300
Subject: restored SL-14027 (merge conflict)

---
 indra/newview/llfloatereditenvironmentbase.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp
index e888144b6a..2850951668 100644
--- a/indra/newview/llfloatereditenvironmentbase.cpp
+++ b/indra/newview/llfloatereditenvironmentbase.cpp
@@ -262,7 +262,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons
         {
             const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
             LLUUID parent_id = mInventoryItem->getParentUUID();
-            if (marketplacelistings_id == parent_id)
+            if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID()))
             {
                 parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
             }
-- 
cgit v1.2.3


From 0dd53d7b5b934ee4fdc312f26ec58530f5b45091 Mon Sep 17 00:00:00 2001
From: Callum Prentice <callum@lindenlab.com>
Date: Thu, 29 Apr 2021 15:59:19 -0700
Subject: Expose the flag to turn automatic VAD on and off.  We will likely
 keep it off since that appears to be working well for us but others may want
 to turn in on

---
 indra/newview/app_settings/settings.xml | 12 +++++++++-
 indra/newview/llvoicevivox.cpp          | 41 ++++++++++++++++++++-------------
 indra/newview/llvoicevivox.h            |  2 +-
 3 files changed, 37 insertions(+), 18 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 07f9511cf2..dcbbf64a97 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14426,7 +14426,17 @@
       <integer>44125</integer>
     </map>
 
-
+  <key>VivoxVadAuto</key>
+  <map>
+    <key>Comment</key>
+    <string>A flag indicating if the automatic VAD is enabled (1) or disabled (0). The individual settings are ignored if the auto-mode is enabled</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>U32</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
   <key>VivoxVadHangover</key>
   <map>
     <key>Comment</key>
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 96ae171eb7..0503ba3f94 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -683,14 +683,17 @@ void LLVivoxVoiceClient::voiceControlCoro()
         bool success = startAndConnectSession();
         if (success)
         {
-			// disable the automatic VAD and explicitly set the initial values of 
-			// the VAD variables ourselves see SL-15072 for more details
+			// enable/disable the automatic VAD and explicitly set the initial values of 
+			// the VAD variables ourselves when it is off - see SL-15072 for more details
+			// note: we set the other parameters too even if the auto VAD is on which is ok
+			unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
 			unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
 			unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
 			unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
-			setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
+			setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
 			
 			// watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
+			gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
 			gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
 			gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
 			gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
@@ -3248,37 +3251,42 @@ void LLVivoxVoiceClient::sendLocalAudioUpdates()
  *
  * From the VIVOX Docs:
  *
- * vad_hangover: The 'Hangover time' - the time (in milliseconds) that it takes
+ * VadAuto: A flag indicating if the automatic VAD is enabled (1) or disabled (0)
+ *
+ * VadHangover: The time (in milliseconds) that it takes
  * for the VAD to switch back to silence from speech mode after the last speech
  * frame has been detected.
  *
- * vad_noise_floor: The 'vad noise floor' - A dimensionless value between 0 and 
+ * VadNoiseFloor: A dimensionless value between 0 and 
  * 20000 (default 576) that controls the maximum level at which the noise floor
  * may be set at by the VAD's noise tracking. Too low of a value will make noise
  * tracking ineffective (A value of 0 disables noise tracking and the VAD then 
  * relies purely on the sensitivity property). Too high of a value will make 
  * long speech classifiable as noise.
  *
- * vad_sensitivity: The 'vad sensitivity' - A dimensionless value between 0 and 
+ * VadSensitivity: A dimensionless value between 0 and 
  * 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds
  * to decreasing the sensitivity of the VAD (i.e. '0' is most sensitive, 
  * while 100 is 'least sensitive')
  */
-void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover,
+void LLVivoxVoiceClient::setupVADParams(unsigned int vad_auto,
+                                        unsigned int vad_hangover,
                                         unsigned int vad_noise_floor,
                                         unsigned int vad_sensitivity)
 {
     std::ostringstream stream;
 
-    // explicitly turn off the automatic VAD even though the
-    // default state is also disabled.
-    const unsigned int vad_auto_enabled = 0;
-
-    // Create a request to set the VAD parameters:
-    LL_INFOS("Voice") << "Disabling the automatic VAD and setting the parameters explicitly." << LL_ENDL;
+    LL_INFOS("Voice") << "Setting the automatic VAD to "
+        << (vad_auto ? "True" : "False")
+		<< " and discrete values to"
+		<< " VadHangover = " << vad_hangover
+		<< ", VadSensitivity = " << vad_sensitivity
+		<< ", VadNoiseFloor = " << vad_noise_floor
+        << LL_ENDL;
 
-    stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
-               << "<VadAuto>" << vad_auto_enabled << "</VadAuto>"
+	// Create a request to set the VAD parameters:
+	stream << "<Request requestId=\"" << mCommandCookie++ << "\" action=\"Aux.SetVadProperties.1\">"
+               << "<VadAuto>" << vad_auto << "</VadAuto>"
                << "<VadHangover>" << vad_hangover << "</VadHangover>"
                << "<VadSensitivity>" << vad_sensitivity << "</VadSensitivity>"
                << "<VadNoiseFloor>" << vad_noise_floor << "</VadNoiseFloor>"
@@ -3293,12 +3301,13 @@ void LLVivoxVoiceClient::setupVADParams(unsigned int vad_hangover,
 void LLVivoxVoiceClient::onVADSettingsChange()
 {
 	// pick up the VAD variables (one of which was changed)
+	unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
 	unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
 	unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
 	unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
 
 	// build a VAD params change request and send it to SLVoice
-	setupVADParams(vad_hangover, vad_noise_floor, vad_sensitivity);
+	setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
 }
 
 /////////////////////////////
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 960030659d..75ff5429f3 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -474,7 +474,7 @@ protected:
 	/////////////////////////////
 	// VAD changes
 	// disable auto-VAD and configure VAD parameters explicitly
-	void setupVADParams(unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
+	void setupVADParams(unsigned int vad_auto, unsigned int vad_hangover, unsigned int vad_noise_floor, unsigned int vad_sensitivity);
 	void onVADSettingsChange();
 
 	/////////////////////////////
-- 
cgit v1.2.3


From 8a33636e8f56f8d1229b3f76ed6205ce8087048d Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 30 Apr 2021 16:27:20 +0300
Subject: SL-13395 Don't hide empty outfit folders

Outfit folders can be created, managed and deleted by users, they should stay visible
---
 indra/newview/llviewerfoldertype.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index afa84a5afc..f770db31dd 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -130,7 +130,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 	addEntry(LLFolderType::FT_FAVORITE, 			new ViewerFolderEntry("Favorites",				"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
 
 	addEntry(LLFolderType::FT_CURRENT_OUTFIT, 		new ViewerFolderEntry("Current Outfit",			"Inv_SysOpen",			"Inv_SysClosed",		TRUE,      false));
-	addEntry(LLFolderType::FT_OUTFIT, 				new ViewerFolderEntry("New Outfit",				"Inv_LookFolderOpen",	"Inv_LookFolderClosed",	TRUE,      true));
+	addEntry(LLFolderType::FT_OUTFIT, 				new ViewerFolderEntry("New Outfit",				"Inv_LookFolderOpen",	"Inv_LookFolderClosed",	TRUE,      false));
 	addEntry(LLFolderType::FT_MY_OUTFITS, 			new ViewerFolderEntry("My Outfits",				"Inv_SysOpen",			"Inv_SysClosed",		TRUE,      true));
 	addEntry(LLFolderType::FT_MESH, 				new ViewerFolderEntry("Meshes",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
 	addEntry(LLFolderType::FT_SETTINGS, 		    new ViewerFolderEntry("Settings",			    "Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
-- 
cgit v1.2.3


From 95d8085fa42ca73773a06f2bd5622f69aef0e598 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 10 May 2021 15:21:51 -0400
Subject: SL-10297: Make LLSingletonBase::llerrs() et al. runtime variadic.

Instead of accepting a fixed list of (const char* p1="", etc.), accept
(std::initializer_list<std::string_view>). Accepting a
std::initializer_list<T> in your parameter list allows coding (e.g.)
func({T0, T1, T2, ... });
-- in other words, you can pass the initializer_list a brace-enclosed list of
an arbitrary number of instances of T.

Using std::string_view instead of const char* means we can pass *either* const
char* or std::string. string_view is cheaply constructed from either, allowing
uniform treatment within the function.

Constructing string_view from std::string simply extracts the pointer and
length from the std::string.

Constructing string_view from const char* (e.g. a "string literal") requires
scanning the string for its terminating nul byte -- but that would be
necessary even if the scan were deferred until the function body. Since
string_view stores the length, the scan still happens only once.
---
 indra/llcommon/llsingleton.cpp | 66 ++++++++++++++++++----------------
 indra/llcommon/llsingleton.h   | 81 ++++++++++++++++++++----------------------
 2 files changed, 75 insertions(+), 72 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index ad933154c2..d0dcd463ff 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -39,8 +39,7 @@
 #include <stdexcept>
 
 namespace {
-void log(LLError::ELevel level,
-         const char* p1, const char* p2, const char* p3, const char* p4);
+void log(LLError::ELevel level, std::initializer_list<std::string_view>);
 } // anonymous namespace
 
 // Our master list of all LLSingletons is itself an LLSingleton. We used to
@@ -218,8 +217,8 @@ void LLSingletonBase::pop_initializing()
 
     if (list.empty())
     {
-        logerrs("Underflow in stack of currently-initializing LLSingletons at ",
-                classname(this).c_str(), "::getInstance()");
+        logerrs({"Underflow in stack of currently-initializing LLSingletons at ",
+                classname(this), "::getInstance()"});
     }
 
     // Now we know list.back() exists: capture it
@@ -240,9 +239,9 @@ void LLSingletonBase::pop_initializing()
     // Now validate the newly-popped LLSingleton.
     if (back != this)
     {
-        logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ",
-                classname(this).c_str(), "::getInstance() trying to pop ",
-                classname(back).c_str());
+        logerrs({"Push/pop mismatch in stack of currently-initializing LLSingletons: ",
+                classname(this), "::getInstance() trying to pop ",
+                classname(back)});
     }
 
     // log AFTER popping so logging singletons don't cry circularity
@@ -331,15 +330,15 @@ void LLSingletonBase::capture_dependency()
                 //
                 // Example: LLNotifications singleton initializes default channels.
                 // Channels register themselves with singleton once done.
-                logdebugs("LLSingleton circularity: ", out.str().c_str(),
-                    classname(this).c_str(), "");
+                logdebugs({"LLSingleton circularity: ", out.str(),
+                          classname(this)});
             }
             else
             {
                 // Actual circularity with other singleton (or single singleton is used extensively).
                 // Dependency can be unclear.
-                logwarns("LLSingleton circularity: ", out.str().c_str(),
-                    classname(this).c_str(), "");
+                logwarns({"LLSingleton circularity: ", out.str(),
+                         classname(this)});
             }
         }
         else
@@ -352,8 +351,8 @@ void LLSingletonBase::capture_dependency()
             if (current->mDepends.insert(this).second)
             {
                 // only log the FIRST time we hit this dependency!
-                logdebugs(classname(current).c_str(),
-                          " depends on ", classname(this).c_str());
+                logdebugs({classname(current),
+                          " depends on ", classname(this)});
             }
         }
     }
@@ -401,7 +400,7 @@ LLSingletonBase::vec_t LLSingletonBase::dep_sort()
 
 void LLSingletonBase::cleanup_()
 {
-    logdebugs("calling ", classname(this).c_str(), "::cleanupSingleton()");
+    logdebugs({"calling ", classname(this), "::cleanupSingleton()"});
     try
     {
         cleanupSingleton();
@@ -427,23 +426,23 @@ void LLSingletonBase::deleteAll()
             if (! sp->mDeleteSingleton)
             {
                 // This Should Not Happen... but carry on.
-                logwarns(name.c_str(), "::mDeleteSingleton not initialized!");
+                logwarns({name, "::mDeleteSingleton not initialized!"});
             }
             else
             {
                 // properly initialized: call it.
-                logdebugs("calling ", name.c_str(), "::deleteSingleton()");
+                logdebugs({"calling ", name, "::deleteSingleton()"});
                 // From this point on, DO NOT DEREFERENCE sp!
                 sp->mDeleteSingleton();
             }
         }
         catch (const std::exception& e)
         {
-            logwarns("Exception in ", name.c_str(), "::deleteSingleton(): ", e.what());
+            logwarns({"Exception in ", name, "::deleteSingleton(): ", e.what()});
         }
         catch (...)
         {
-            logwarns("Unknown exception in ", name.c_str(), "::deleteSingleton()");
+            logwarns({"Unknown exception in ", name, "::deleteSingleton()"});
         }
     }
 }
@@ -451,40 +450,47 @@ void LLSingletonBase::deleteAll()
 /*---------------------------- Logging helpers -----------------------------*/
 namespace {
 
-void log(LLError::ELevel level,
-         const char* p1, const char* p2, const char* p3, const char* p4)
+void log(LLError::ELevel level, std::initializer_list<std::string_view> args)
 {
-    LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL;
+    LL_VLOGS(level, "LLSingleton");
+        for (auto arg : args)
+        {
+            LL_CONT << arg;
+        }
+    LL_ENDL;
 }
 
 } // anonymous namespace        
 
 //static
-void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4)
+void LLSingletonBase::logwarns(std::initializer_list<std::string_view> args)
 {
-    log(LLError::LEVEL_WARN, p1, p2, p3, p4);
+    log(LLError::LEVEL_WARN, args);
 }
 
 //static
-void LLSingletonBase::loginfos(const char* p1, const char* p2, const char* p3, const char* p4)
+void LLSingletonBase::loginfos(std::initializer_list<std::string_view> args)
 {
-    log(LLError::LEVEL_INFO, p1, p2, p3, p4);
+    log(LLError::LEVEL_INFO, args);
 }
 
 //static
-void LLSingletonBase::logdebugs(const char* p1, const char* p2, const char* p3, const char* p4)
+void LLSingletonBase::logdebugs(std::initializer_list<std::string_view> args)
 {
-    log(LLError::LEVEL_DEBUG, p1, p2, p3, p4);
+    log(LLError::LEVEL_DEBUG, args);
 }
 
 //static
-void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4)
+void LLSingletonBase::logerrs(std::initializer_list<std::string_view> args)
 {
-    log(LLError::LEVEL_ERROR, p1, p2, p3, p4);
+    log(LLError::LEVEL_ERROR, args);
     // The other important side effect of LL_ERRS() is
     // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
     std::ostringstream out;
-    out << p1 << p2 << p3 << p4;
+    for (auto arg : args)
+    {
+        out << arg;
+    }
     auto crash = LLError::getFatalFunction();
     if (crash)
     {
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 30a5b21cf8..b9570d42db 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -34,6 +34,7 @@
 #include "lockstatic.h"
 #include "llthread.h"               // on_main_thread()
 #include "llmainthreadtask.h"
+#include <initializer_list>
 
 class LLSingletonBase: private boost::noncopyable
 {
@@ -111,14 +112,10 @@ protected:
     void capture_dependency();
 
     // delegate logging calls to llsingleton.cpp
-    static void logerrs(const char* p1, const char* p2="",
-                        const char* p3="", const char* p4="");
-    static void logwarns(const char* p1, const char* p2="",
-                         const char* p3="", const char* p4="");
-    static void loginfos(const char* p1, const char* p2="",
-                         const char* p3="", const char* p4="");
-    static void logdebugs(const char* p1, const char* p2="",
-                          const char* p3="", const char* p4="");
+    static void logerrs  (std::initializer_list<std::string_view>);
+    static void logwarns (std::initializer_list<std::string_view>);
+    static void loginfos (std::initializer_list<std::string_view>);
+    static void logdebugs(std::initializer_list<std::string_view>);
     static std::string demangle(const char* mangled);
     // these classname() declarations restate template functions declared in
     // llerror.h because we avoid #including that here
@@ -327,8 +324,8 @@ private:
             // init stack to its previous size BEFORE logging so log-machinery
             // LLSingletons don't record a dependency on DERIVED_TYPE!
             LLSingleton_manage_master<DERIVED_TYPE>().reset_initializing(prev_size);
-            logwarns("Error constructing ", classname<DERIVED_TYPE>().c_str(),
-                     ": ", err.what());
+            logwarns({"Error constructing ", classname<DERIVED_TYPE>(),
+                     ": ", err.what()});
             // There isn't a separate EInitState value meaning "we attempted
             // to construct this LLSingleton subclass but could not," so use
             // DELETED. That seems slightly more appropriate than UNINITIALIZED.
@@ -356,8 +353,8 @@ private:
             // BEFORE logging, so log-machinery LLSingletons don't record a
             // dependency on DERIVED_TYPE!
             pop_initializing(lk->mInstance);
-            logwarns("Error in ", classname<DERIVED_TYPE>().c_str(),
-                     "::initSingleton(): ", err.what());
+            logwarns({"Error in ", classname<DERIVED_TYPE>(),
+                     "::initSingleton(): ", err.what()});
             // Get rid of the instance entirely. This call depends on our
             // recursive_mutex. We could have a deleteSingleton(LockStatic&)
             // overload and pass lk, but we don't strictly need it.
@@ -506,9 +503,9 @@ public:
             case CONSTRUCTING:
                 // here if DERIVED_TYPE's constructor (directly or indirectly)
                 // calls DERIVED_TYPE::getInstance()
-                logerrs("Tried to access singleton ",
-                        classname<DERIVED_TYPE>().c_str(),
-                        " from singleton constructor!");
+                logerrs({"Tried to access singleton ",
+                        classname<DERIVED_TYPE>(),
+                        " from singleton constructor!"});
                 return nullptr;
 
             case INITIALIZING:
@@ -523,9 +520,9 @@ public:
 
             case DELETED:
                 // called after deleteSingleton()
-                logwarns("Trying to access deleted singleton ",
-                         classname<DERIVED_TYPE>().c_str(),
-                         " -- creating new instance");
+                logwarns({"Trying to access deleted singleton ",
+                         classname<DERIVED_TYPE>(),
+                         " -- creating new instance"});
                 // fall through
             case UNINITIALIZED:
             case QUEUED:
@@ -552,8 +549,8 @@ public:
         } // unlock 'lk'
 
         // Per the comment block above, dispatch to the main thread.
-        loginfos(classname<DERIVED_TYPE>().c_str(),
-                 "::getInstance() dispatching to main thread");
+        loginfos({classname<DERIVED_TYPE>(),
+                 "::getInstance() dispatching to main thread"});
         auto instance = LLMainThreadTask::dispatch(
             [](){
                 // VERY IMPORTANT to call getInstance() on the main thread,
@@ -563,16 +560,16 @@ public:
                 // the main thread processes them, only the FIRST such request
                 // actually constructs the instance -- every subsequent one
                 // simply returns the existing instance.
-                loginfos(classname<DERIVED_TYPE>().c_str(),
-                         "::getInstance() on main thread");
+                loginfos({classname<DERIVED_TYPE>(),
+                         "::getInstance() on main thread"});
                 return getInstance();
             });
         // record the dependency chain tracked on THIS thread, not the main
         // thread (consider a getInstance() overload with a tag param that
         // suppresses dep tracking when dispatched to the main thread)
         capture_dependency(instance);
-        loginfos(classname<DERIVED_TYPE>().c_str(),
-                 "::getInstance() returning on requesting thread");
+        loginfos({classname<DERIVED_TYPE>(),
+                 "::getInstance() returning on requesting thread"});
         return instance;
     }
 
@@ -641,16 +638,16 @@ private:
         // For organizational purposes this function shouldn't be called twice
         if (lk->mInitState != super::UNINITIALIZED)
         {
-            super::logerrs("Tried to initialize singleton ",
-                           super::template classname<DERIVED_TYPE>().c_str(),
-                           " twice!");
+            super::logerrs({"Tried to initialize singleton ",
+                           super::template classname<DERIVED_TYPE>(),
+                           " twice!"});
             return nullptr;
         }
         else if (on_main_thread())
         {
             // on the main thread, simply construct instance while holding lock
-            super::logdebugs(super::template classname<DERIVED_TYPE>().c_str(),
-                             "::initParamSingleton()");
+            super::logdebugs({super::template classname<DERIVED_TYPE>(),
+                             "::initParamSingleton()"});
             super::constructSingleton(lk, std::forward<Args>(args)...);
             return lk->mInstance;
         }
@@ -662,8 +659,8 @@ private:
             lk->mInitState = super::QUEUED;
             // very important to unlock here so main thread can actually process
             lk.unlock();
-            super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
-                            "::initParamSingleton() dispatching to main thread");
+            super::loginfos({super::template classname<DERIVED_TYPE>(),
+                            "::initParamSingleton() dispatching to main thread"});
             // Normally it would be the height of folly to reference-bind
             // 'args' into a lambda to be executed on some other thread! By
             // the time that thread executed the lambda, the references would
@@ -674,12 +671,12 @@ private:
             // references.
             auto instance = LLMainThreadTask::dispatch(
                 [&](){
-                    super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
-                                    "::initParamSingleton() on main thread");
+                    super::loginfos({super::template classname<DERIVED_TYPE>(),
+                                    "::initParamSingleton() on main thread"});
                     return initParamSingleton_(std::forward<Args>(args)...);
                 });
-            super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
-                            "::initParamSingleton() returning on requesting thread");
+            super::loginfos({super::template classname<DERIVED_TYPE>(),
+                            "::initParamSingleton() returning on requesting thread"});
             return instance;
         }
     }
@@ -707,14 +704,14 @@ public:
         {
         case super::UNINITIALIZED:
         case super::QUEUED:
-            super::logerrs("Uninitialized param singleton ",
-                           super::template classname<DERIVED_TYPE>().c_str());
+            super::logerrs({"Uninitialized param singleton ",
+                           super::template classname<DERIVED_TYPE>()});
             break;
 
         case super::CONSTRUCTING:
-            super::logerrs("Tried to access param singleton ",
-                           super::template classname<DERIVED_TYPE>().c_str(),
-                           " from singleton constructor!");
+            super::logerrs({"Tried to access param singleton ",
+                           super::template classname<DERIVED_TYPE>(),
+                           " from singleton constructor!"});
             break;
 
         case super::INITIALIZING:
@@ -726,8 +723,8 @@ public:
             return lk->mInstance;
 
         case super::DELETED:
-            super::logerrs("Trying to access deleted param singleton ",
-                           super::template classname<DERIVED_TYPE>().c_str());
+            super::logerrs({"Trying to access deleted param singleton ",
+                           super::template classname<DERIVED_TYPE>()});
             break;
         }
 
-- 
cgit v1.2.3


From c9fc4349b7d4ab1f5a7bfc0125014a96a07e51a3 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Tue, 11 May 2021 21:42:14 -0400
Subject: SL-10297: Move LL_ERRS crash location into the LL_ERRS macro itself.

Introduce Oz's LLERROR_CRASH macro analogous to the old LLError::crashAndLoop()
function. Change LL_ENDL macro so that, after calling flush(), if the CallSite
is for LEVEL_ERROR, we invoke LLERROR_CRASH right there.

Change the meaning of LLError::FatalFunction. It used to be responsible for
the actual crash (hence crashAndLoop()). Now, instead, its role is to disrupt
control flow in some other way if you DON'T want to crash: throw an exception,
or call exit() or some such. Any FatalFunction that returns normally will fall
into the new crash in LL_ENDL.

Accordingly, the new default FatalFunction is a no-op lambda. This eliminates
the need to test for empty (not set) FatalFunction in Log::flush().

Remove LLError::crashAndLoop() because the official LL_ERRS crash is now in
LL_ENDL.

One of the two common use cases for setFatalFunction() used to be to intercept
control in the last moments before crashing -- not to crash or to avoid
crashing, but to capture the LL_ERRS message in some way. Especially when
that's temporary, though (e.g. LLLeap), saving and restoring the previous
FatalFunction only works when the lifespans of the relevant objects are
strictly LIFO.

Either way, that's a misuse of FatalFunction. Fortunately the Recorder
mechanism exactly addresses that case. Introduce a GenericRecorder template
subclass, with LLError::addGenericRecorder(callable) that accepts a callable
with suitable (level, message) signature, instantiates a GenericRecorder, adds
it to the logging machinery and returns the RecorderPtr for possible later use
with removeRecorder().

Change llappviewer.cpp's errorCallback() to an addGenericRecorder() callable.
Its role was simply to update gDebugInfo["FatalMessage"] with the LL_ERRS
message, then call writeDebugInfo(), before calling crashAndLoop() to finish
crashing. Remove the crashAndLoop() call, retaining the gDebugInfo logic. Pass
errorCallback() to LLError::addGenericRecorder() instead of setFatalFunction().

Oddly, errorCallback()'s crashAndLoop() call was conditional on a compile-time
SHADER_CRASH_NONFATAL symbol. The new mechanism provides no way to support
SHADER_CRASH_NONFATAL -- it is a Bad Idea to return normally from any LL_ERRS
invocation!

Rename LLLeapImpl::fatalFunction() to onError(). Instead of passing it to
LLError::setFatalFunction(), pass it to addGenericRecorder(). Capture the
returned RecorderPtr in mRecorder, replacing mPrevFatalFunction. Then
~LLLeapImpl() calls removeRecorder(mRecorder) instead of restoring
mPrevFatalFunction (which, as noted above, was order-sensitive).

Of course, every enabled Recorder is called with every log message. onError()
and errorCallback() must specifically test for calls with LEVEL_ERROR.

LLSingletonBase::logerrs() used to call LLError::getFatalFunction(), check the
return and call it if non-empty, else call LLError::crashAndLoop(). Replace
all that with LLERROR_CRASH.

Remove from llappviewer.cpp the watchdog_llerrs_callback() and
watchdog_killer_callback() functions. watchdog_killer_callback(), passed to
Watchdog::init(), used to setFatalFunction(watchdog_llerrs_callback) and then
invoke LL_ERRS() -- which seems a bit roundabout. watchdog_llerrs_callback(),
in turn, replicated much of the logic in the primary errorCallback() function
before replicating the crash from llwatchdog.cpp's default_killer_callback().

Instead, pass LLWatchdog::init() a lambda that invokes the LL_ERRS() message
formerly found in watchdog_killer_callback(). It no longer needs to override
FatalFunction with watchdog_llerrs_callback() because errorCallback() will
still be called as a Recorder, obviating watchdog_llerrs_callback()'s first
half; and LL_ENDL will handle the crash, obviating the second half.

Remove from llappviewer.cpp the static fast_exit() function, which was simply
an alias for _exit() acceptable to boost::bind(). Use a lambda directly
calling _exit() instead of using boost::bind() at all.

In the CaptureLog class in llcommon/tests/wrapllerrs.h, instead of statically
referencing the wouldHaveCrashed() function from test.cpp, simply save and
restore the current FatalFunction across the LLError::saveAndResetSettings()
call.

llerror_test.cpp calls setFatalFunction(fatalCall), where fatalCall() was a
function that simply set a fatalWasCalled bool rather than actually crashing
in any way. Of course, that implementation would now lead to crashing the test
program. Make fatalCall() throw a new FatalWasCalled exception. Introduce a
CATCH(LL_ERRS("tag"), "message") macro that expands to:
LL_ERRS("tag") << "message" << LL_ENDL;
within a try/catch block that catches FatalWasCalled and sets the same bool.

Change all existing LL_ERRS() in llerror_test.cpp to corresponding CATCH()
calls. In fact there's also an LL_DEBUGS(bad tag) invocation that exercises an
LL_ERRS internal to llerror.cpp; wrap that too.
---
 indra/llcommon/llerror.cpp            | 37 +++----------------
 indra/llcommon/llerror.h              | 22 +++++++++---
 indra/llcommon/llerrorcontrol.h       | 57 +++++++++++++++++++++++------
 indra/llcommon/llleap.cpp             | 48 ++++++++++++-------------
 indra/llcommon/llsingleton.cpp        | 15 +-------
 indra/llcommon/tests/llerror_test.cpp | 58 +++++++++++++++++++-----------
 indra/llcommon/tests/wrapllerrs.h     | 22 ++++++------
 indra/newview/llappviewer.cpp         | 67 +++++++++--------------------------
 8 files changed, 159 insertions(+), 167 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index f876b8ee4a..9d775dcef3 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -549,7 +549,7 @@ namespace LLError
 		mFileLevelMap(),
 		mTagLevelMap(),
 		mUniqueLogMessages(),
-		mCrashFunction(NULL),
+		mCrashFunction([](const std::string&){}),
 		mTimeFunction(NULL),
 		mRecorders(),
 		mShouldLogCallCounter(0)
@@ -728,7 +728,6 @@ namespace
 		LLError::setDefaultLevel(LLError::LEVEL_INFO);
 		LLError::setAlwaysFlush(true);
 		LLError::setEnabledLogTypesMask(0xFFFFFFFF);
-		LLError::setFatalFunction(LLError::crashAndLoop);
 		LLError::setTimeFunction(LLError::utcTime);
 
 		// log_to_stderr is only false in the unit and integration tests to keep builds quieter
@@ -1436,7 +1435,7 @@ namespace LLError
 
 		if (site.mPrintOnce)
 		{
-            std::ostringstream message_stream;
+			std::ostringstream message_stream;
 
 			std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message);
 			if (messageIter != s->mUniqueLogMessages.end())
@@ -1457,8 +1456,8 @@ namespace LLError
 				message_stream << "ONCE: ";
 				s->mUniqueLogMessages[message] = 1;
 			}
-            message_stream << message;
-            message = message_stream.str();
+			message_stream << message;
+			message = message_stream.str();
 		}
 		
 		writeToRecorders(site, message);
@@ -1466,10 +1465,7 @@ namespace LLError
 		if (site.mLevel == LEVEL_ERROR)
 		{
 			g->mFatalMessage = message;
-			if (s->mCrashFunction)
-			{
-				s->mCrashFunction(message);
-			}
+			s->mCrashFunction(message);
 		}
 	}
 }
@@ -1533,29 +1529,6 @@ namespace LLError
 		return s->mShouldLogCallCounter;
 	}
 
-#if LL_WINDOWS
-		// VC80 was optimizing the error away.
-		#pragma optimize("", off)
-#endif
-	void crashAndLoop(const std::string& message)
-	{
-		// Now, we go kaboom!
-		int* make_me_crash = NULL;
-
-		*make_me_crash = 0;
-
-		while(true)
-		{
-			// Loop forever, in case the crash didn't work?
-		}
-		
-		// this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever.
-		exit(EXIT_FAILURE);
-	}
-#if LL_WINDOWS
-		#pragma optimize("", on)
-#endif
-
 	std::string utcTime()
 	{
 		time_t now = time(NULL);
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index ffaa464d77..f8c0d03aea 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -382,11 +382,23 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 #define LL_NEWLINE '\n'
 
-#define LL_ENDL                               \
-			LLError::End();                   \
-			LLError::Log::flush(_out, _site); \
-		}                                     \
-	} while(0)
+// Use this only in LL_ERRS or in a place that LL_ERRS may not be used
+#define LLERROR_CRASH         \
+{                             \
+    int* make_me_crash = NULL;\
+    *make_me_crash = 0;       \
+    exit(*make_me_crash);     \
+}
+
+#define LL_ENDL                                         \
+            LLError::End();                             \
+            LLError::Log::flush(_out, _site);           \
+            if (_site.mLevel == LLError::LEVEL_ERROR)   \
+            {                                           \
+                LLERROR_CRASH                           \
+            }                                           \
+        }                                               \
+    } while(0)
 
 // NEW Macros for debugging, allow the passing of a string tag
 
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 25786d5457..e87bb7bf35 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -94,14 +94,16 @@ namespace LLError
 	*/
 
 	typedef boost::function<void(const std::string&)> FatalFunction;
-	LL_COMMON_API void crashAndLoop(const std::string& message);
-		// Default fatal function: access null pointer and loops forever
 
 	LL_COMMON_API void setFatalFunction(const FatalFunction&);
-		// The fatal function will be called when an message of LEVEL_ERROR
+		// The fatal function will be called after an message of LEVEL_ERROR
 		// is logged.  Note: supressing a LEVEL_ERROR message from being logged
 		// (by, for example, setting a class level to LEVEL_NONE), will keep
-		// the that message from causing the fatal funciton to be invoked.
+		// that message from causing the fatal function to be invoked.
+		// The passed FatalFunction will be the LAST log function called
+		// before LL_ERRS crashes its caller. A FatalFunction can throw an
+		// exception, or call exit(), to bypass the crash. It MUST disrupt the
+		// flow of control because no caller expects LL_ERRS to return.
 
 	LL_COMMON_API FatalFunction getFatalFunction();
 		// Retrieve the previously-set FatalFunction
@@ -147,14 +149,14 @@ namespace LLError
 		virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
 			// use the level for better display, not for filtering
 
-        virtual bool enabled() { return true; }
+		virtual bool enabled() { return true; }
 
 		bool wantsTime();
 		bool wantsTags();
 		bool wantsLevel();
 		bool wantsLocation(); 
 		bool wantsFunctionName();
-        bool wantsMultiline();
+		bool wantsMultiline();
 
 		void showTime(bool show);
 		void showTags(bool show);
@@ -165,15 +167,35 @@ namespace LLError
 
 	protected:
 		bool mWantsTime;
-        bool mWantsTags;
-        bool mWantsLevel;
-        bool mWantsLocation;
-        bool mWantsFunctionName;
-        bool mWantsMultiline;
+		bool mWantsTags;
+		bool mWantsLevel;
+		bool mWantsLocation;
+		bool mWantsFunctionName;
+		bool mWantsMultiline;
 	};
 
 	typedef boost::shared_ptr<Recorder> RecorderPtr;
 
+    /**
+     * Instantiate GenericRecorder with a callable(level, message) to get
+     * control on every log message without having to code an explicit
+     * Recorder subclass.
+     */
+    template <typename CALLABLE>
+    class GenericRecorder: public Recorder
+    {
+    public:
+        GenericRecorder(const CALLABLE& callable):
+            mCallable(callable)
+        {}
+        void recordMessage(LLError::ELevel level, const std::string& message) override
+        {
+            mCallable(level, message);
+        }
+    private:
+        CALLABLE mCallable;
+    };
+
 	/**
 	 * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership
 	 * while still ensuring that the allocated memory is eventually freed
@@ -181,6 +203,19 @@ namespace LLError
 	LL_COMMON_API void addRecorder(RecorderPtr);
 	LL_COMMON_API void removeRecorder(RecorderPtr);
 		// each error message is passed to each recorder via recordMessage()
+	/**
+	 * Call addGenericRecorder() with a callable(level, message) to get
+	 * control on every log message without having to code an explicit
+	 * Recorder subclass. Save the returned RecorderPtr if you later want to
+	 * call removeRecorder().
+	 */
+	template <typename CALLABLE>
+	RecorderPtr addGenericRecorder(const CALLABLE& callable)
+	{
+		RecorderPtr ptr{ new GenericRecorder<CALLABLE>(callable) };
+		addRecorder(ptr);
+		return ptr;
+	}
 
 	LL_COMMON_API void logToFile(const std::string& filename);
 	LL_COMMON_API void logToStderr();
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index cf8f8cc6a5..e8ea0ab398 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -59,7 +59,6 @@ public:
         // pump name -- so it should NOT need tweaking for uniqueness.
         mReplyPump(LLUUID::generateNewID().asString()),
         mExpect(0),
-        mPrevFatalFunction(LLError::getFatalFunction()),
         // Instantiate a distinct LLLeapListener for this plugin. (Every
         // plugin will want its own collection of managed listeners, etc.)
         // Pass it a callback to our connect() method, so it can send events
@@ -146,7 +145,9 @@ public:
             .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1));
 
         // For our lifespan, intercept any LL_ERRS so we can notify plugin
-        LLError::setFatalFunction(boost::bind(&LLLeapImpl::fatalFunction, this, _1));
+        mRecorder = LLError::addGenericRecorder(
+            [this](LLError::ELevel level, const std::string& message)
+            { onError(level, message); });
 
         // Send child a preliminary event reporting our own reply-pump name --
         // which would otherwise be pretty tricky to guess!
@@ -162,8 +163,7 @@ public:
     virtual ~LLLeapImpl()
     {
         LL_DEBUGS("LLLeap") << "destroying LLLeap(\"" << mDesc << "\")" << LL_ENDL;
-        // Restore original FatalFunction
-        LLError::setFatalFunction(mPrevFatalFunction);
+        LLError::removeRecorder(mRecorder);
     }
 
     // Listener for failed launch attempt
@@ -377,28 +377,28 @@ public:
         return false;
     }
 
-    void fatalFunction(const std::string& error)
+    void onError(LLError::ELevel level, const std::string& error)
     {
-        // Notify plugin
-        LLSD event;
-        event["type"] = "error";
-        event["error"] = error;
-        mReplyPump.post(event);
-
-        // All the above really accomplished was to buffer the serialized
-        // event in our WritePipe. Have to pump mainloop a couple times to
-        // really write it out there... but time out in case we can't write.
-        LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
-        LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
-        LLSD nop;
-        F64 until = (LLTimer::getElapsedSeconds() + 2).value();
-        while (childin.size() && LLTimer::getElapsedSeconds() < until)
+        if (level == LLError::LEVEL_ERROR)
         {
-            mainloop.post(nop);
+            // Notify plugin
+            LLSD event;
+            event["type"] = "error";
+            event["error"] = error;
+            mReplyPump.post(event);
+
+            // All the above really accomplished was to buffer the serialized
+            // event in our WritePipe. Have to pump mainloop a couple times to
+            // really write it out there... but time out in case we can't write.
+            LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
+            LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+            LLSD nop;
+            F64 until = (LLTimer::getElapsedSeconds() + 2).value();
+            while (childin.size() && LLTimer::getElapsedSeconds() < until)
+            {
+                mainloop.post(nop);
+            }
         }
-
-        // forward the call to the previous FatalFunction
-        mPrevFatalFunction(error);
     }
 
 private:
@@ -421,7 +421,7 @@ private:
         mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection;
     boost::scoped_ptr<LLEventPump::Blocker> mBlocker;
     LLProcess::ReadPipe::size_type mExpect;
-    LLError::FatalFunction mPrevFatalFunction;
+    LLError::RecorderPtr mRecorder;
     boost::scoped_ptr<LLLeapListener> mListener;
 };
 
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index d0dcd463ff..4b1666563e 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -486,20 +486,7 @@ void LLSingletonBase::logerrs(std::initializer_list<std::string_view> args)
     log(LLError::LEVEL_ERROR, args);
     // The other important side effect of LL_ERRS() is
     // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
-    std::ostringstream out;
-    for (auto arg : args)
-    {
-        out << arg;
-    }
-    auto crash = LLError::getFatalFunction();
-    if (crash)
-    {
-        crash(out.str());
-    }
-    else
-    {
-        LLError::crashAndLoop(out.str());
-    }
+    LLERROR_CRASH;
 }
 
 std::string LLSingletonBase::demangle(const char* mangled)
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 8e1f4c14ac..148c18aabe 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -26,6 +26,7 @@
  */
 
 #include <vector>
+#include <stdexcept>
 
 #include "linden_common.h"
 
@@ -69,21 +70,41 @@ namespace
 
 namespace
 {
-	static bool fatalWasCalled;
-	void fatalCall(const std::string&) { fatalWasCalled = true; }
+	static bool fatalWasCalled = false;
+    struct FatalWasCalled: public std::runtime_error
+    {
+        FatalWasCalled(const std::string& what): std::runtime_error(what) {}
+    };
+    void fatalCall(const std::string& msg) { throw FatalWasCalled(msg); }
 }
 
+// Because we use LLError::setFatalFunction(fatalCall), any LL_ERRS call we
+// issue will throw FatalWasCalled. But we want the test program to continue.
+// So instead of writing:
+// LL_ERRS("tag") << "some message" << LL_ENDL;
+// write:
+// CATCH(LL_ERRS("tag"), "some message");
+#define CATCH(logcall, expr)                    \
+    try                                         \
+    {                                           \
+        logcall << expr << LL_ENDL;             \
+    }                                           \
+    catch (const FatalWasCalled&)               \
+    {                                           \
+        fatalWasCalled = true;                  \
+    }
+
 namespace tut
 {
 	class TestRecorder : public LLError::Recorder
 	{
 	public:
 		TestRecorder()
-            {
-                showTime(false);
-            }
+			{
+				showTime(false);
+			}
 		virtual ~TestRecorder()
-            {}
+			{}
 
 		virtual void recordMessage(LLError::ELevel level,
 						   const std::string& message)
@@ -252,7 +273,7 @@ namespace
 		LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL;
 		LL_INFOS("WriteTag") << "two" << LL_ENDL;
 		LL_WARNS("WriteTag") << "three" << LL_ENDL;
-		LL_ERRS("WriteTag") << "four" << LL_ENDL;
+		CATCH(LL_ERRS("WriteTag"), "four");
 	}
 };
 
@@ -380,7 +401,7 @@ namespace
 
 	std::string errorReturningLocation()
 	{
-		LL_ERRS() << "die" << LL_ENDL;	int this_line = __LINE__;
+		int this_line = __LINE__;	CATCH(LL_ERRS(), "die");
 		return locationString(this_line);
 	}
 }
@@ -701,7 +722,7 @@ public:
 	static void doDebug()	{ LL_DEBUGS() << "add dice" << LL_ENDL; }
 	static void doInfo()	{ LL_INFOS()  << "any idea" << LL_ENDL; }
 	static void doWarn()	{ LL_WARNS()  << "aim west" << LL_ENDL; }
-	static void doError()	{ LL_ERRS()   << "ate eels" << LL_ENDL; }
+	static void doError()	{ CATCH(LL_ERRS(), "ate eels"); }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
@@ -712,7 +733,7 @@ public:
 	static void doDebug()	{ LL_DEBUGS() << "bed down" << LL_ENDL; }
 	static void doInfo()	{ LL_INFOS()  << "buy iron" << LL_ENDL; }
 	static void doWarn()	{ LL_WARNS()  << "bad word" << LL_ENDL; }
-	static void doError()	{ LL_ERRS()   << "big easy" << LL_ENDL; }
+	static void doError()	{ CATCH(LL_ERRS(), "big easy"); }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
@@ -874,13 +895,10 @@ namespace tut
 namespace
 {
     std::string writeTagWithSpaceReturningLocation()
-	{
-        LL_DEBUGS("Write Tag") << "not allowed" << LL_ENDL;	int this_line = __LINE__;
-        
-        std::ostringstream location;
-        location << LLError::abbreviateFile(__FILE__).c_str() << "(" << this_line << ")";
-        return location.str();
-	}
+    {
+        int this_line = __LINE__; CATCH(LL_DEBUGS("Write Tag"), "not allowed");
+        return locationString(this_line);
+    }
 };
 
 namespace tut
@@ -894,9 +912,9 @@ namespace tut
 
         std::string location = writeTagWithSpaceReturningLocation();
         std::string expected = "Space is not allowed in a log tag at " + location;
-		ensure_message_field_equals(0, LEVEL_FIELD, "ERROR");
-		ensure_message_field_equals(0, MSG_FIELD, expected);
-		ensure("fatal callback called", fatalWasCalled);
+        ensure_message_field_equals(0, LEVEL_FIELD, "ERROR");
+        ensure_message_field_equals(0, MSG_FIELD, expected);
+        ensure("fatal callback called", fatalWasCalled);
     }
 }
 
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index b07d5afbd8..3779fb41bc 100644
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -44,10 +44,6 @@
 #include <list>
 #include <string>
 
-// statically reference the function in test.cpp... it's short, we could
-// replicate, but better to reuse
-extern void wouldHaveCrashed(const std::string& message);
-
 struct WrapLLErrs
 {
     WrapLLErrs():
@@ -59,7 +55,8 @@ struct WrapLLErrs
         mPriorFatal(LLError::getFatalFunction())
     {
         // Make LL_ERRS call our own operator() method
-        LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1));
+        LLError::setFatalFunction(
+            [this](const std::string& message){ (*this)(message); });
     }
 
     ~WrapLLErrs()
@@ -199,11 +196,13 @@ public:
         // with that output. If it turns out that saveAndResetSettings() has
         // some bad effect, give up and just let the DEBUG level log messages
         // display.
-		: boost::noncopyable(),
+        : boost::noncopyable(),
+        mFatalFunction(LLError::getFatalFunction()),
         mOldSettings(LLError::saveAndResetSettings()),
-		mRecorder(new CaptureLogRecorder())
+        mRecorder(new CaptureLogRecorder())
     {
-        LLError::setFatalFunction(wouldHaveCrashed);
+        // reinstate the FatalFunction we just reset
+        LLError::setFatalFunction(mFatalFunction);
         LLError::setDefaultLevel(level);
         LLError::addRecorder(mRecorder);
     }
@@ -219,17 +218,18 @@ public:
     /// for the sought string.
     std::string messageWith(const std::string& search, bool required=true)
     {
-		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);
+        return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required);
     }
 
     std::ostream& streamto(std::ostream& out) const
     {
-		return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);
+        return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out);
     }
 
 private:
+    LLError::FatalFunction mFatalFunction;
     LLError::SettingsStoragePtr mOldSettings;
-	LLError::RecorderPtr mRecorder;
+    LLError::RecorderPtr mRecorder;
 };
 
 #endif /* ! defined(LL_WRAPLLERRS_H) */
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0b2cdff36c..b03e821d32 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -760,17 +760,6 @@ public:
 	}
 };
 
-namespace {
-// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide
-// this little helper function.
-void fast_exit(int rc)
-{
-	_exit(rc);
-}
-
-
-}
-
 
 bool LLAppViewer::init()
 {
@@ -822,9 +811,9 @@ bool LLAppViewer::init()
 	if (rc >= 0)
 	{
 		// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
-		// fast_exit() rather than exit() because normal cleanup depends too
+		// _exit() rather than exit() because normal cleanup depends too
 		// much on successful startup!
-		LLError::setFatalFunction(boost::bind(fast_exit, rc));
+		LLError::setFatalFunction([rc](const std::string&){ _exit(rc); });
 	}
 
     mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
@@ -2185,28 +2174,6 @@ bool LLAppViewer::cleanup()
 	return true;
 }
 
-// A callback for LL_ERRS() to call during the watchdog error.
-void watchdog_llerrs_callback(const std::string &error_string)
-{
-	gLLErrorActivated = true;
-
-	gDebugInfo["FatalMessage"] = error_string;
-	LLAppViewer::instance()->writeDebugInfo();
-
-#ifdef LL_WINDOWS
-	RaiseException(0,0,0,0);
-#else
-	raise(SIGQUIT);
-#endif
-}
-
-// A callback for the watchdog to call.
-void watchdog_killer_callback()
-{
-	LLError::setFatalFunction(watchdog_llerrs_callback);
-	LL_ERRS() << "Watchdog killer event" << LL_ENDL;
-}
-
 bool LLAppViewer::initThreads()
 {
 	static const bool enable_threads = true;
@@ -2241,24 +2208,23 @@ bool LLAppViewer::initThreads()
 	return true;
 }
 
-void errorCallback(const std::string &error_string)
+void errorCallback(LLError::ELevel level, const std::string &error_string)
 {
+    if (level == LLError::LEVEL_ERROR)
+    {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
+        OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
 #endif
 
-	//Set the ErrorActivated global so we know to create a marker file
-	gLLErrorActivated = true;
-
-	gDebugInfo["FatalMessage"] = error_string;
-	// We're not already crashing -- we simply *intend* to crash. Since we
-	// haven't actually trashed anything yet, we can afford to write the whole
-	// static info file.
-	LLAppViewer::instance()->writeDebugInfo();
+        //Set the ErrorActivated global so we know to create a marker file
+        gLLErrorActivated = true;
 
-#ifndef SHADER_CRASH_NONFATAL
-	LLError::crashAndLoop(error_string);
-#endif
+        gDebugInfo["FatalMessage"] = error_string;
+        // We're not already crashing -- we simply *intend* to crash. Since we
+        // haven't actually trashed anything yet, we can afford to write the whole
+        // static info file.
+        LLAppViewer::instance()->writeDebugInfo();
+    }
 }
 
 void LLAppViewer::initLoggingAndGetLastDuration()
@@ -2269,7 +2235,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
                                 ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
                                 );
-	LLError::setFatalFunction(errorCallback);
+	LLError::addGenericRecorder(&errorCallback);
 	//LLError::setTimeFunction(getRuntime);
 
 	// Remove the last ".old" log file.
@@ -3030,7 +2996,8 @@ bool LLAppViewer::initWindow()
 
 	if (use_watchdog)
 	{
-		LLWatchdog::getInstance()->init(watchdog_killer_callback);
+		LLWatchdog::getInstance()->init(
+			[](){ LL_ERRS() << "Watchdog killer event" << LL_ENDL; });
 	}
 	LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;
 
-- 
cgit v1.2.3


From 147c66d67ce83778fc3f102dd132ec095e6032fc Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 09:46:49 -0400
Subject: SL-10297: Simplify implementation of LLSingletonBase::logwarns() etc.

Introduce 'string_params' typedef for std::initialization_list<std::string>,
and make logwarns(), loginfos(), logdebugs() and logerrs() accept const
string_params&.

Eliminate the central log() function in llsingleton.cpp that used LL_VLOGS().
To cache the result of a (moderately expensive) Log::shouldLog() call,
LL_VLOGS() wants its CallSite object to be static -- but of course the
shouldLog() result will differ for different ELevel values, so LL_VLOGS()
instantiates a static array of CallSite instances. It seems silly to funnel
distinct logwarns(), etc., functions through a common log() function only to
have LL_VLOGS() tease apart ELevel values again. Instead, make logwarns()
directly invoke LL_WARNS(), and similarly for the rest.

To reduce boilerplate in these distinct functions, teach std::ostream how to
stream a string_params instance by looping over its elements. Then each
logwarns(), etc., function can simply stream its string_params argument to
LL_WARNS() or whichever.

In particular, eliminate the LLERROR_CRASH macro in logerrs(). The fact that
it invokes LL_ERRS() ensures that its LL_ENDL macro will crash the viewer.
---
 indra/llcommon/llsingleton.cpp | 37 +++++++++++++++----------------------
 indra/llcommon/llsingleton.h   | 11 +++++++----
 2 files changed, 22 insertions(+), 26 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 4b1666563e..6b1986d0e9 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -38,10 +38,6 @@
 #include <sstream>
 #include <stdexcept>
 
-namespace {
-void log(LLError::ELevel level, std::initializer_list<std::string_view>);
-} // anonymous namespace
-
 // Our master list of all LLSingletons is itself an LLSingleton. We used to
 // store it in a function-local static, but that could get destroyed before
 // the last of the LLSingletons -- and ~LLSingletonBase() definitely wants to
@@ -450,43 +446,40 @@ void LLSingletonBase::deleteAll()
 /*---------------------------- Logging helpers -----------------------------*/
 namespace {
 
-void log(LLError::ELevel level, std::initializer_list<std::string_view> args)
+std::ostream& operator<<(std::ostream& out, const LLSingletonBase::string_params& args)
 {
-    LL_VLOGS(level, "LLSingleton");
-        for (auto arg : args)
-        {
-            LL_CONT << arg;
-        }
-    LL_ENDL;
+    // However many args there are in args, stream each of them to 'out'.
+    for (auto arg : args)
+    {
+        out << arg;
+    }
+    return out;
 }
 
 } // anonymous namespace        
 
 //static
-void LLSingletonBase::logwarns(std::initializer_list<std::string_view> args)
+void LLSingletonBase::logwarns(const string_params& args)
 {
-    log(LLError::LEVEL_WARN, args);
+    LL_WARNS("LLSingleton") << args << LL_ENDL;
 }
 
 //static
-void LLSingletonBase::loginfos(std::initializer_list<std::string_view> args)
+void LLSingletonBase::loginfos(const string_params& args)
 {
-    log(LLError::LEVEL_INFO, args);
+    LL_INFOS("LLSingleton") << args << LL_ENDL;
 }
 
 //static
-void LLSingletonBase::logdebugs(std::initializer_list<std::string_view> args)
+void LLSingletonBase::logdebugs(const string_params& args)
 {
-    log(LLError::LEVEL_DEBUG, args);
+    LL_DEBUGS("LLSingleton") << args << LL_ENDL;
 }
 
 //static
-void LLSingletonBase::logerrs(std::initializer_list<std::string_view> args)
+void LLSingletonBase::logerrs(const string_params& args)
 {
-    log(LLError::LEVEL_ERROR, args);
-    // The other important side effect of LL_ERRS() is
-    // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
-    LLERROR_CRASH;
+    LL_ERRS("LLSingleton") << args << LL_ENDL;
 }
 
 std::string LLSingletonBase::demangle(const char* mangled)
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index b9570d42db..2eb39c6c8c 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -112,10 +112,13 @@ protected:
     void capture_dependency();
 
     // delegate logging calls to llsingleton.cpp
-    static void logerrs  (std::initializer_list<std::string_view>);
-    static void logwarns (std::initializer_list<std::string_view>);
-    static void loginfos (std::initializer_list<std::string_view>);
-    static void logdebugs(std::initializer_list<std::string_view>);
+public:
+    typedef std::initializer_list<std::string_view> string_params;
+protected:
+    static void logerrs  (const string_params&);
+    static void logwarns (const string_params&);
+    static void loginfos (const string_params&);
+    static void logdebugs(const string_params&);
     static std::string demangle(const char* mangled);
     // these classname() declarations restate template functions declared in
     // llerror.h because we avoid #including that here
-- 
cgit v1.2.3


From 5b96ee0e10923a00ddb3836d4dc3c5f912ca4330 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 12:02:57 -0400
Subject: SL-10297: Eliminate llerror.cpp's Globals::messageStream and bool.

Instead of a single std::ostringstream instance shared by all callers, even
those on different threads, make each of the relevant lllog_test_() and
llcallstacks macros instantiate independent (stack) std::ostringstream
objects. lllog_test_() is called by LL_DEBUGS(), LLINFOS(), LL_WARNS(),
LL_ERRS(), LL_VLOGS() et al.

Eliminate LLError::Log::out(), whose sole function was to arbitrate use of
that shared std::ostringstream. Amusingly, if the lock couldn't be locked or
if messageStreamInUse was set, out() would allocate a new (heap!)
std::ostringstream anyway, which would then have to be freed by flush().

Make both LLError::Log::flush() overloads accept const std::ostringstream&.
Make LL_ENDL pass the local _out instance. This eliminates the need to check
whether the passed std::ostringstream* references the shared instance and
(if so) reset it or (if not) delete it.

Make LLError::LLCallStacks::insert() accept the local _out instance as non-
const std::ostream&, rather than acquiring and returning std::ostringstream*.
Make end() accept the local instance as const std::ostringstream&.
---
 indra/llcommon/llerror.cpp | 73 +++++++---------------------------------------
 indra/llcommon/llerror.h   | 30 +++++++++----------
 2 files changed, 26 insertions(+), 77 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 9d775dcef3..f7594ed815 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -442,8 +442,6 @@ namespace
     protected:
 		Globals();
 	public:
-		std::ostringstream messageStream;
-		bool messageStreamInUse;
 		std::string mFatalMessage;
 
 		void addCallSite(LLError::CallSite&);
@@ -453,12 +451,7 @@ namespace
 		CallSiteVector callSites;
 	};
 
-	Globals::Globals()
-		: messageStream(),
-		messageStreamInUse(false),
-		callSites()
-	{
-	}
+	Globals::Globals() {}
 
     Globals* Globals::getInstance()
     {
@@ -1359,25 +1352,7 @@ namespace LLError
 	}
 
 
-	std::ostringstream* Log::out()
-	{
-		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
-
-		if (lock.isLocked())
-		{
-			Globals* g = Globals::getInstance();
-
-			if (!g->messageStreamInUse)
-			{
-				g->messageStreamInUse = true;
-				return &g->messageStream;
-			}
-		}
-
-		return new std::ostringstream;
-	}
-
-	void Log::flush(std::ostringstream* out, char* message)
+	void Log::flush(const std::ostringstream& out, char* message)
 	{
 		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
 		if (!lock.isLocked())
@@ -1385,31 +1360,18 @@ namespace LLError
 			return;
 		}
 
-		if(strlen(out->str().c_str()) < 128)
+		if(strlen(out.str().c_str()) < 128)
 		{
-			strcpy(message, out->str().c_str());
+			strcpy(message, out.str().c_str());
 		}
 		else
 		{
-			strncpy(message, out->str().c_str(), 127);
+			strncpy(message, out.str().c_str(), 127);
 			message[127] = '\0' ;
 		}
-
-		Globals* g = Globals::getInstance();
-		if (out == &g->messageStream)
-		{
-			g->messageStream.clear();
-			g->messageStream.str("");
-			g->messageStreamInUse = false;
-		}
-		else
-		{
-			delete out;
-		}
-		return ;
 	}
 
-	void Log::flush(std::ostringstream* out, const CallSite& site)
+	void Log::flush(const std::ostringstream& out, const CallSite& site)
 	{
 		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
 		if (!lock.isLocked())
@@ -1420,18 +1382,7 @@ namespace LLError
 		Globals* g = Globals::getInstance();
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
-		std::string message = out->str();
-		if (out == &g->messageStream)
-		{
-			g->messageStream.clear();
-			g->messageStream.str("");
-			g->messageStreamInUse = false;
-		}
-		else
-		{
-			delete out;
-		}
-
+		std::string message = out.str();
 
 		if (site.mPrintOnce)
 		{
@@ -1600,15 +1551,13 @@ namespace LLError
     }
 
     //static
-    std::ostringstream* LLCallStacks::insert(const char* function, const int line)
+    void LLCallStacks::insert(std::ostream& out, const char* function, const int line)
     {
-        std::ostringstream* _out = LLError::Log::out();
-        *_out << function << " line " << line << " " ;
-        return _out ;
+        out << function << " line " << line << " " ;
     }
 
     //static
-    void LLCallStacks::end(std::ostringstream* _out)
+    void LLCallStacks::end(const std::ostringstream& out)
     {
         LLMutexTrylock lock(getMutex<STACKS_MUTEX>(), 5);
         if (!lock.isLocked())
@@ -1626,7 +1575,7 @@ namespace LLError
             clear() ;
         }
 
-        LLError::Log::flush(_out, sBuffer[sIndex++]) ;
+        LLError::Log::flush(out, sBuffer[sIndex++]) ;
     }
 
     //static
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index f8c0d03aea..51423350e6 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -198,9 +198,8 @@ namespace LLError
 	{
 	public:
 		static bool shouldLog(CallSite&);
-		static std::ostringstream* out();
-		static void flush(std::ostringstream* out, char* message);
-		static void flush(std::ostringstream*, const CallSite&);
+		static void flush(const std::ostringstream& out, char* message);
+		static void flush(const std::ostringstream&, const CallSite&);
 		static std::string demangle(const char* mangled);
 		/// classname<TYPE>()
 		template <typename T>
@@ -289,10 +288,10 @@ namespace LLError
               
     public:   
         static void push(const char* function, const int line) ;
-        static std::ostringstream* insert(const char* function, const int line) ;
+        static void insert(std::ostream& out, const char* function, const int line) ;
         static void print() ;
         static void clear() ;
-        static void end(std::ostringstream* _out) ;
+        static void end(const std::ostringstream& out) ;
         static void cleanup();
     };
 
@@ -306,10 +305,11 @@ namespace LLError
 //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
 #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
 
-#define llcallstacks                                                                      \
-	{                                                                                     \
-       std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \
-       (*_out)
+#define llcallstacks                                                    \
+	{                                                                   \
+		std::ostringstream _out;                                        \
+		LLError::LLCallStacks::insert(_out, __FUNCTION__, __LINE__) ;   \
+		_out
 
 #define llcallstacksendl                   \
 		LLError::End();                    \
@@ -355,11 +355,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 		static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
 		lllog_test_()
 
-#define lllog_test_()                                       \
-		if (LL_UNLIKELY(_site.shouldLog()))                 \
-		{                                                   \
-			std::ostringstream* _out = LLError::Log::out(); \
-			(*_out)
+#define lllog_test_()                           \
+		if (LL_UNLIKELY(_site.shouldLog()))     \
+		{                                       \
+			std::ostringstream _out;            \
+			_out
 
 #define lllog_site_args_(level, once, tags)                 \
 	level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG),    \
@@ -378,7 +378,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 //	LL_CONT << " for " << t << " seconds" << LL_ENDL;
 //	
 //Such computation is done iff the message will be logged.
-#define LL_CONT	(*_out)
+#define LL_CONT	_out
 
 #define LL_NEWLINE '\n'
 
-- 
cgit v1.2.3


From 91c20363eee4e1e02435e0ee74867cdb3f6c7136 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 13:37:24 -0400
Subject: SL-10297: Get rid of LLError::LLCallStacks::allocateStackBuffer().

Also freeStackBuffer() and all the funky classic-C string management of a big
flat buffer divided into exactly 512 128-byte strings. Define StringVector as
a std::vector<std::string>, and use that instead.

Retain the behavior of clearing the vector if it exceeds 512 entries.

This eliminates the LLError::Log::flush(const std::ostringstream&, char*)
overload as well, with its baffling mix of std::string and classic-C (e.g.
strlen(out.str().c_str()).

If we absolutely MUST use a big memory pool for performance reasons, let's
use StringVector with allocators.
---
 indra/llcommon/llerror.cpp | 88 ++++++++--------------------------------------
 indra/llcommon/llerror.h   | 10 +++---
 2 files changed, 18 insertions(+), 80 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index f7594ed815..8355df9045 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1352,25 +1352,6 @@ namespace LLError
 	}
 
 
-	void Log::flush(const std::ostringstream& out, char* message)
-	{
-		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
-		if (!lock.isLocked())
-		{
-			return;
-		}
-
-		if(strlen(out.str().c_str()) < 128)
-		{
-			strcpy(message, out.str().c_str());
-		}
-		else
-		{
-			strncpy(message, out.str().c_str(), 127);
-			message[127] = '\0' ;
-		}
-	}
-
 	void Log::flush(const std::ostringstream& out, const CallSite& site)
 	{
 		LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5);
@@ -1496,33 +1477,7 @@ namespace LLError
 
 namespace LLError
 {     
-	char** LLCallStacks::sBuffer = NULL ;
-	S32    LLCallStacks::sIndex  = 0 ;
-
-	//static
-    void LLCallStacks::allocateStackBuffer()
-    {
-        if(sBuffer == NULL)
-        {
-            sBuffer = new char*[512] ;
-            sBuffer[0] = new char[512 * 128] ;
-            for(S32 i = 1 ; i < 512 ; i++)
-            {
-                sBuffer[i] = sBuffer[i-1] + 128 ;
-            }
-            sIndex = 0 ;
-        }
-    }
-
-    void LLCallStacks::freeStackBuffer()
-    {
-        if(sBuffer != NULL)
-        {
-            delete [] sBuffer[0] ;
-            delete [] sBuffer ;
-            sBuffer = NULL ;
-        }
-    }
+    LLCallStacks::StringVector LLCallStacks::sBuffer ;
 
     //static
     void LLCallStacks::push(const char* function, const int line)
@@ -1533,21 +1488,14 @@ namespace LLError
             return;
         }
 
-        if(sBuffer == NULL)
-        {
-            allocateStackBuffer();
-        }
-
-        if(sIndex > 511)
+        if(sBuffer.size() > 511)
         {
             clear() ;
         }
 
-        strcpy(sBuffer[sIndex], function) ;
-        sprintf(sBuffer[sIndex] + strlen(function), " line: %d ", line) ;
-        sIndex++ ;
-
-        return ;
+        std::ostringstream out;
+        insert(out, function, line);
+        sBuffer.push_back(out.str());
     }
 
     //static
@@ -1565,17 +1513,12 @@ namespace LLError
             return;
         }
 
-        if(sBuffer == NULL)
-        {
-            allocateStackBuffer();
-        }
-
-        if(sIndex > 511)
+        if(sBuffer.size() > 511)
         {
             clear() ;
         }
 
-        LLError::Log::flush(out, sBuffer[sIndex++]) ;
+        sBuffer.push_back(out.str());
     }
 
     //static
@@ -1587,33 +1530,30 @@ namespace LLError
             return;
         }
 
-        if(sIndex > 0)
+        if(! sBuffer.empty())
         {
             LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL;
-            while(sIndex > 0)
+            for (StringVector::const_reverse_iterator ri(sBuffer.rbegin()), re(sBuffer.rend());
+                 ri != re; ++ri)
             {                  
-                sIndex-- ;
-                LL_INFOS() << sBuffer[sIndex] << LL_ENDL;
+                LL_INFOS() << (*ri) << LL_ENDL;
             }
             LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
         }
 
-        if(sBuffer != NULL)
-        {
-            freeStackBuffer();
-        }
+        cleanup();
     }
 
     //static
     void LLCallStacks::clear()
     {
-        sIndex = 0 ;
+        sBuffer.clear();
     }
 
     //static
     void LLCallStacks::cleanup()
     {
-        freeStackBuffer();
+        clear();
     }
 
     std::ostream& operator<<(std::ostream& out, const LLStacktrace&)
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 51423350e6..d439136ca8 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -29,7 +29,9 @@
 #define LL_LLERROR_H
 
 #include <sstream>
+#include <string>
 #include <typeinfo>
+#include <vector>
 
 #include "stdtypes.h"
 
@@ -198,7 +200,6 @@ namespace LLError
 	{
 	public:
 		static bool shouldLog(CallSite&);
-		static void flush(const std::ostringstream& out, char* message);
 		static void flush(const std::ostringstream&, const CallSite&);
 		static std::string demangle(const char* mangled);
 		/// classname<TYPE>()
@@ -280,11 +281,8 @@ namespace LLError
     class LL_COMMON_API LLCallStacks
     {
     private:
-        static char**  sBuffer ;
-        static S32     sIndex ;
-
-        static void allocateStackBuffer();
-        static void freeStackBuffer();
+        typedef std::vector<std::string> StringVector;
+        static StringVector sBuffer ;
               
     public:   
         static void push(const char* function, const int line) ;
-- 
cgit v1.2.3


From 28862ab53b9e532bf6ff789743d80b33af10f395 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 14:21:27 -0400
Subject: SL-10297: Clean up a few merge glitches.

---
 indra/newview/llappviewer.cpp | 29 ++++++++++++-----------------
 indra/test/test.cpp           | 22 ++++++++--------------
 2 files changed, 20 insertions(+), 31 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c44690ac25..7d7d41fe22 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2298,10 +2298,6 @@ void LLAppViewer::initLoggingAndGetLastDuration()
 	{
 		LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
 	}
-
-    // TBD - temporary location for fatal hook (should be above, but for now it logs...)
-    LL_DEBUGS("FatalHook") << "initial setting of default fatalhook" << LL_ENDL;
-    LLError::setFatalHook(fatalErrorHook);
 }
 
 bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
@@ -2998,16 +2994,15 @@ bool LLAppViewer::initWindow()
 		use_watchdog = bool(watchdog_enabled_setting);
 	}
 
-    LL_INFOS("AppInit") << "watchdog"
-                        << (use_watchdog ? " " : " NOT ")
-                        << "enabled"
-                        << " (setting = " << watchdog_enabled_setting << ")"
-                        << LL_ENDL;
+	LL_INFOS("AppInit") << "watchdog"
+						<< (use_watchdog ? " " : " NOT ")
+						<< "enabled"
+						<< " (setting = " << watchdog_enabled_setting << ")"
+						<< LL_ENDL;
 
 	if (use_watchdog)
 	{
-		LLWatchdog::getInstance()->init(
-			[](){ LL_ERRS() << "Watchdog killer event" << LL_ENDL; });
+		LLWatchdog::getInstance()->init();
 	}
 
 	LLNotificationsUI::LLNotificationManager::getInstance();
@@ -3441,8 +3436,8 @@ void LLAppViewer::writeSystemInfo()
 	gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
 	gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
 
-	gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value());
-	gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
+	gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value());
+	gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
 	gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple();
 
 	// The user is not logged on yet, but record the current grid choice login url
@@ -3461,11 +3456,11 @@ void LLAppViewer::writeSystemInfo()
 	// and can read this value from the debug_info.log.
 	// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
 	// then the value of "CrashNotHandled" will be set to true.
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true;
+	gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true);
 #else // LL_BUGSPLAT
 	// "CrashNotHandled" is obsolete; it used (not very successsfully)
     // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze
-	gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)false;
+	gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false);
 #endif // ! LL_BUGSPLAT
 
 	// Insert crash host url (url to post crash log to) if configured. This insures
@@ -3497,7 +3492,7 @@ void LLAppViewer::writeSystemInfo()
     gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile");
 	gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName();
 	gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
-	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
+	gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin());
 	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
     gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
 
@@ -3627,7 +3622,7 @@ void LLAppViewer::handleViewerCrash()
 
 	// The crash is being handled here so set this value to false.
 	// Otherwise the crash logger will think this crash was a freeze.
-	gDebugInfo["Dynamic"]["CrashNotHandled"] = (LLSD::Boolean)false;
+	gDebugInfo["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false);
 
 	//Write out the crash status file
 	//Use marker file style setup, as that's the simplest, especially since
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 571f502861..87c4a8d8a3 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -75,18 +75,7 @@
 
 #include <fstream>
 
-LLError::ErrFatalHookResult wouldHaveCrashed(const std::string& message)
-{
-#if LL_MSVC
-#pragma warning (push)
-#pragma warning (disable : 4702) // warning C4702: unreachable code
-#endif
-	tut::fail("fatal error message: " + message);
-    return LLError::ERR_DO_NOT_CRASH;
-#if LL_MSVC
-#pragma warning (pop)
-#endif
-}
+void wouldHaveCrashed(const std::string& message);
 
 namespace tut
 {
@@ -157,7 +146,7 @@ public:
 		mOldSettings(LLError::saveAndResetSettings()),
 		mRecorder(new RecordToTempFile(pool))
 	{
-		LLError::setFatalHook(wouldHaveCrashed);
+		LLError::setFatalFunction(wouldHaveCrashed);
 		LLError::setDefaultLevel(level);
 		LLError::addRecorder(mRecorder);
 	}
@@ -523,6 +512,11 @@ void stream_groups(std::ostream& s, const char* app)
 	}
 }
 
+void wouldHaveCrashed(const std::string& message)
+{
+	tut::fail("llerrs message: " + message);
+}
+
 static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
 
 int main(int argc, char **argv)
@@ -632,7 +626,7 @@ int main(int argc, char **argv)
 			replayer.reset(new LLReplayLogReal(level, gAPRPoolp));
 		}
 	}
-	LLError::setFatalHook(wouldHaveCrashed);
+	LLError::setFatalFunction(wouldHaveCrashed);
 	std::string test_app_name(argv[0]);
 	std::string test_log = test_app_name + ".log";
 	LLFile::remove(test_log);
-- 
cgit v1.2.3


From d10badf0d23f48665239117838c5daf0fd667e01 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 16:26:53 -0400
Subject: SL-10297: #include <string_view> in llsingleton.h

---
 indra/llcommon/llsingleton.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 2eb39c6c8c..163c08099f 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -27,14 +27,15 @@
 
 #include <boost/noncopyable.hpp>
 #include <boost/unordered_set.hpp>
+#include <initializer_list>
 #include <list>
-#include <vector>
+#include <string_view>
 #include <typeinfo>
+#include <vector>
 #include "mutex.h"
 #include "lockstatic.h"
 #include "llthread.h"               // on_main_thread()
 #include "llmainthreadtask.h"
-#include <initializer_list>
 
 class LLSingletonBase: private boost::noncopyable
 {
-- 
cgit v1.2.3


From 28deadab5b37880314a58eff095ae2844a9ebbac Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 17:08:15 -0400
Subject: SL-10297: Need VS switch /std:c++17 to use std::string_view.

---
 indra/cmake/00-Common.cmake | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 8aea50e02b..83041d0663 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -66,7 +66,8 @@ if (WINDOWS)
   # CP changed to only append the flag for 32bit builds - on 64bit builds,
   # locally at least, the build output is spammed with 1000s of 'D9002'
   # warnings about this switch being ignored.
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")  
+  # We need std::string_view, but that's not available without /std:c++17.
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /std:c++17")  
   if( ADDRESS_SIZE EQUAL 32 )
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")  
   endif()
-- 
cgit v1.2.3


From a58eea7419ac9aec6ca08bcfca17ee14bf62e72c Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 22:30:34 -0400
Subject: SL-10297: Revert "Need VS switch /std:c++17 to use std::string_view."

This reverts commit 28deadab5b37880314a58eff095ae2844a9ebbac.

Going there implies other changes, will take up on another branch.
---
 indra/cmake/00-Common.cmake | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 83041d0663..8aea50e02b 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -66,8 +66,7 @@ if (WINDOWS)
   # CP changed to only append the flag for 32bit builds - on 64bit builds,
   # locally at least, the build output is spammed with 1000s of 'D9002'
   # warnings about this switch being ignored.
-  # We need std::string_view, but that's not available without /std:c++17.
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /std:c++17")  
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")  
   if( ADDRESS_SIZE EQUAL 32 )
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")  
   endif()
-- 
cgit v1.2.3


From 24501dfa0ee3fd6f5755deb1bc5261cd297a2bc7 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 12 May 2021 22:35:09 -0400
Subject: SL-10297: Use initializer_list<std::string> vs. <std::string_view>.

This is somewhat more expensive for string literals, but switching to
std::string_view implies more extensive changes, to be considered separately.
---
 indra/llcommon/llsingleton.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 163c08099f..7c81d65a8b 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -29,7 +29,6 @@
 #include <boost/unordered_set.hpp>
 #include <initializer_list>
 #include <list>
-#include <string_view>
 #include <typeinfo>
 #include <vector>
 #include "mutex.h"
@@ -114,7 +113,7 @@ protected:
 
     // delegate logging calls to llsingleton.cpp
 public:
-    typedef std::initializer_list<std::string_view> string_params;
+    typedef std::initializer_list<const std::string> string_params;
 protected:
     static void logerrs  (const string_params&);
     static void logwarns (const string_params&);
-- 
cgit v1.2.3


From a442f8b4513f385952f586f2950645ac5050556f Mon Sep 17 00:00:00 2001
From: Andrey Lihatskiy <alihatskiy@productengine.com>
Date: Thu, 13 May 2021 20:29:01 +0300
Subject: Revert "Merge branch 'DRTVWR-531' into DRTVWR-516-maint"

This reverts commit 07456abe92ab24f373b238f6bd64087c078b7fc3, reversing
changes made to 8a33636e8f56f8d1229b3f76ed6205ce8087048d.
---
 indra/media_plugins/cef/media_plugin_cef.cpp | 12 +-----------
 indra/newview/viewer_manifest.py             |  6 ------
 2 files changed, 1 insertion(+), 17 deletions(-)

(limited to 'indra')

diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index c658f35480..0bb62d79ff 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -525,18 +525,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
 				mCEFLib->setOnJSDialogCallback(std::bind(&MediaPluginCEF::onJSDialogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
 				
 				dullahan::dullahan_settings settings;
-#if LL_WINDOWS
-				// As of CEF version 83+, for Windows versions, we need to tell CEF 
-				// where the host helper process is since this DLL is not in the same
-				// dir as the executable that loaded it (SLPlugin.exe). The code in 
-				// Dullahan that tried to figure out the location automatically uses 
-				// the location of the exe which isn't helpful so we tell it explicitly.
-				char cur_dir_str[MAX_PATH];
-				GetCurrentDirectoryA(MAX_PATH, cur_dir_str);
-				settings.host_process_path = std::string(cur_dir_str);
-#endif
 				settings.accept_language_list = mHostLanguage;
-				settings.background_color = 0xff282828; // close to Viewer background color
+				settings.background_color = 0xffffffff;
 				settings.cache_enabled = true;
 				settings.root_cache_path = mRootCachePath;
 				settings.cache_path = mCachePath;
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 0207256e96..adac7af712 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -614,12 +614,6 @@ class WindowsManifest(ViewerManifest):
                 self.path("msvcp140.dll")
                 self.path("vcruntime140.dll")
 
-            # as of CEF 88, this (apparently software rendering support)
-            # folder is required - likely a Chromium bug - but including
-            # for now until the root cause is found - it's tiny
-            with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')):
-                self.path("swiftshader/")
-
             # CEF files common to all configurations
             with self.prefix(src=os.path.join(pkgdir, 'resources')):
                 self.path("cef.pak")
-- 
cgit v1.2.3


From 646cde231d72fb217c6d34cd95d941a24544ca3a Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Wed, 19 May 2021 12:37:40 +0300
Subject: SL-15268 update the description of the 'VivoxVadSensitivity' debug
 setting

---
 indra/newview/app_settings/settings.xml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index a3f54def1c..6cf296cf62 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14449,8 +14449,7 @@
   <key>VivoxVadSensitivity</key>
   <map>
     <key>Comment</key>
-    <string>
-      A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string>
+    <string>A dimensionless value between 0 and 100, indicating the 'sensitivity of the VAD'. Increasing this value corresponds to decreasing the sensitivity of the VAD and 0 is turned off altogether</string>
     <key>Persist</key>
     <integer>1</integer>
     <key>Type</key>
-- 
cgit v1.2.3


From 823f97ac59e4eb11746cc38d330c223313a5a8fa Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 21 May 2021 20:06:41 +0300
Subject: SL-15272 Bugsplat crashes at condition wait()

Made sure all waits will be triggered, won't loop back and that in case of http queue it had some time to trigger
---
 indra/llcommon/llthread.cpp                     |  3 ++-
 indra/llcorehttp/_httpreplyqueue.cpp            |  1 -
 indra/llcorehttp/_httpreplyqueue.h              |  1 -
 indra/llcorehttp/_httprequestqueue.cpp          | 12 +++++++++---
 indra/llcorehttp/_httprequestqueue.h            |  2 +-
 indra/llcorehttp/_httpservice.cpp               |  6 +++++-
 indra/newview/llappearancemgr.cpp               |  6 +++---
 indra/newview/llcompilequeue.cpp                |  2 +-
 indra/newview/lldelayedgestureerror.cpp         |  2 +-
 indra/newview/llmeshrepository.cpp              | 19 ++++++++++---------
 indra/newview/lloutfitgallery.cpp               |  2 +-
 indra/newview/lltoolmgr.cpp                     |  2 +-
 indra/newview/llviewerassetstorage.cpp          |  2 +-
 indra/win_crash_logger/llcrashloggerwindows.cpp |  2 +-
 14 files changed, 36 insertions(+), 26 deletions(-)

(limited to 'indra')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 0b9dec969c..e9e6b5e73c 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -354,8 +354,9 @@ void LLThread::setQuitting()
     {
         mStatus = QUITTING;
     }
+    // It's only safe to remove mRunCondition if all locked threads were notified
+    mRunCondition->broadcast();
     mDataLock->unlock();
-    wake();
 }
 
 // static
diff --git a/indra/llcorehttp/_httpreplyqueue.cpp b/indra/llcorehttp/_httpreplyqueue.cpp
index 2b138f3ad5..229bfdbe07 100644
--- a/indra/llcorehttp/_httpreplyqueue.cpp
+++ b/indra/llcorehttp/_httpreplyqueue.cpp
@@ -56,7 +56,6 @@ void HttpReplyQueue::addOp(const HttpReplyQueue::opPtr_t &op)
 
 		mQueue.push_back(op);
 	}
-	mQueueCV.notify_all();
 }
 
 
diff --git a/indra/llcorehttp/_httpreplyqueue.h b/indra/llcorehttp/_httpreplyqueue.h
index 928ee10a83..33e205c1c9 100644
--- a/indra/llcorehttp/_httpreplyqueue.h
+++ b/indra/llcorehttp/_httpreplyqueue.h
@@ -98,7 +98,6 @@ protected:
 
 	OpContainer							mQueue;
 	LLCoreInt::HttpMutex				mQueueMutex;
-	LLCoreInt::HttpConditionVariable	mQueueCV;
 	
 }; // end class HttpReplyQueue
 
diff --git a/indra/llcorehttp/_httprequestqueue.cpp b/indra/llcorehttp/_httprequestqueue.cpp
index c6f4ad789f..ad72bdcce6 100644
--- a/indra/llcorehttp/_httprequestqueue.cpp
+++ b/indra/llcorehttp/_httprequestqueue.cpp
@@ -142,13 +142,19 @@ void HttpRequestQueue::wakeAll()
 }
 
 
-void HttpRequestQueue::stopQueue()
+bool HttpRequestQueue::stopQueue()
 {
 	{
 		HttpScopedLock lock(mQueueMutex);
 
-		mQueueStopped = true;
-		wakeAll();
+        if (!mQueueStopped)
+        {
+            mQueueStopped = true;
+            wakeAll();
+            return true;
+        }
+        wakeAll();
+        return false;
 	}
 }
 
diff --git a/indra/llcorehttp/_httprequestqueue.h b/indra/llcorehttp/_httprequestqueue.h
index 3c3d134b07..f0296f30e3 100644
--- a/indra/llcorehttp/_httprequestqueue.h
+++ b/indra/llcorehttp/_httprequestqueue.h
@@ -124,7 +124,7 @@ public:
 	/// them on their way.
 	///
 	/// Threading:  callable by any thread.
-	void stopQueue();
+	bool stopQueue();
 	
 protected:
 	static HttpRequestQueue *			sInstance;
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index 34268d94f6..56f52f1b09 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -87,7 +87,11 @@ HttpService::~HttpService()
 		// is a bit tricky.
 		if (mRequestQueue)
 		{
-			mRequestQueue->stopQueue();
+            if (mRequestQueue->stopQueue())
+            {
+                // Give mRequestQueue a chance to finish
+                ms_sleep(10);
+            }
 		}
 		
 		if (mThread)
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index e8a3305645..9fc2e9ead8 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -3626,7 +3626,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
     }
 
     llcoro::suspend();
-    if (LLApp::isQuitting())
+    if (LLApp::isExiting())
     {
         return;
     }
@@ -3693,7 +3693,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
 
         LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData);
 
-        if (LLApp::isQuitting())
+        if (LLApp::isExiting())
         {
             return;
         }
@@ -3733,7 +3733,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
                 LL_WARNS("Avatar") << "Bake retry #" << retryCount << " in " << timeout << " seconds." << LL_ENDL;
 
                 llcoro::suspendUntilTimeout(timeout); 
-                if (LLApp::isQuitting())
+                if (LLApp::isExiting())
                 {
                     return;
                 }
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index 3aaaaf52f5..bf10a9f2b4 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -347,7 +347,7 @@ void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID paren
 bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
     const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
 {
-    if (LLApp::isQuitting())
+    if (LLApp::isExiting())
     {
         // Reply from coroutine came on shutdown
         // We are quiting, don't start any more coroutines!
diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp
index ef1b644ad4..934a38bb8e 100644
--- a/indra/newview/lldelayedgestureerror.cpp
+++ b/indra/newview/lldelayedgestureerror.cpp
@@ -113,7 +113,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
 		}
 	}
 	 
-	if(!LLApp::isQuitting())
+	if(!LLApp::isExiting())
 	{
 		LLNotificationsUtil::add(ent.mNotifyName, args);
 	}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 3e8731dfe6..2c1c1191da 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -881,7 +881,7 @@ void LLMeshRepoThread::run()
 		LL_WARNS(LOG_MESH) << "Convex decomposition unable to be loaded.  Expect severe problems." << LL_ENDL;
 	}
 
-	while (!LLApp::isQuitting())
+	while (!LLApp::isExiting())
 	{
 		// *TODO:  Revise sleep/wake strategy and try to move away
 		// from polling operations in this thread.  We can sleep
@@ -898,7 +898,7 @@ void LLMeshRepoThread::run()
 		
 		mSignal->wait();
 
-		if (LLApp::isQuitting())
+		if (LLApp::isExiting())
 		{
 			break;
 		}
@@ -1168,7 +1168,7 @@ void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id)
 
 void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
 {
-	if (!LLAppViewer::isQuitting())
+	if (!LLAppViewer::isExiting())
 	{
 		loadMeshLOD(mesh_params, lod);
 	}
@@ -2654,7 +2654,7 @@ void LLMeshUploadThread::doWholeModelUpload()
 			LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;
 			
 			mHttpRequest->update(0);
-			while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
+			while (! LLApp::isExiting() && ! finished() && ! isDiscarded())
 			{
 				ms_sleep(sleep_time);
 				sleep_time = llmin(250U, sleep_time + sleep_time);
@@ -2703,7 +2703,7 @@ void LLMeshUploadThread::requestWholeModelFee()
 		U32 sleep_time(10);
 		
 		mHttpRequest->update(0);
-		while (! LLApp::isQuitting() && ! finished() && ! isDiscarded())
+		while (! LLApp::isExiting() && ! finished() && ! isDiscarded())
 		{
 			ms_sleep(sleep_time);
 			sleep_time = llmin(250U, sleep_time + sleep_time);
@@ -3149,7 +3149,7 @@ common_exit:
 
 LLMeshHeaderHandler::~LLMeshHeaderHandler()
 {
-	if (!LLApp::isQuitting())
+	if (!LLApp::isExiting())
 	{
 		if (! mProcessed)
 		{
@@ -3292,7 +3292,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
 
 LLMeshLODHandler::~LLMeshLODHandler()
 {
-	if (! LLApp::isQuitting())
+	if (! LLApp::isExiting())
 	{
 		if (! mProcessed)
 		{
@@ -3553,7 +3553,7 @@ void LLMeshRepository::shutdown()
 		mUploads[i]->discard() ; //discard the uploading requests.
 	}
 
-	mThread->mSignal->signal();
+	mThread->mSignal->broadcast();
 	
 	while (!mThread->isStopped())
 	{
@@ -4682,7 +4682,8 @@ void LLPhysicsDecomp::shutdown()
 	if (mSignal)
 	{
 		mQuitting = true;
-		mSignal->signal();
+		// There is only one wait(), but just in case 'broadcast'
+		mSignal->broadcast();
 
 		while (!isStopped())
 		{
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 1bc08bd0d7..c1b622ffff 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1118,7 +1118,7 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
         }
     }
     
-    if (mGalleryCreated && !LLApp::isQuitting())
+    if (mGalleryCreated && !LLApp::isExiting())
     {
         reArrangeRows();
     }
diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp
index 3fcf193dec..fa2dd60ee0 100644
--- a/indra/newview/lltoolmgr.cpp
+++ b/indra/newview/lltoolmgr.cpp
@@ -405,7 +405,7 @@ void LLToolMgr::clearTransientTool()
 
 void LLToolMgr::onAppFocusLost()
 {
-	if (LLApp::isQuitting())
+	if (LLApp::isExiting())
 		return;
 
 	if (mSelectedTool)
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index acb9e27c55..c1b129750a 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -546,7 +546,7 @@ void LLViewerAssetStorage::assetRequestCoro(
 
     LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts);
 
-    if (LLApp::isQuitting() || !gAssetStorage)
+    if (LLApp::isExiting() || !gAssetStorage)
     {
         // Bail out if result arrives after shutdown has been started.
         return;
diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp
index 267224a79b..0cbe0b0d17 100644
--- a/indra/win_crash_logger/llcrashloggerwindows.cpp
+++ b/indra/win_crash_logger/llcrashloggerwindows.cpp
@@ -498,7 +498,7 @@ bool LLCrashLoggerWindows::frame()
 		
 		MSG msg;
 		memset(&msg, 0, sizeof(msg));
-		while (!LLApp::isQuitting() && GetMessage(&msg, NULL, 0, 0))
+		while (!LLApp::isExiting() && GetMessage(&msg, NULL, 0, 0))
 		{
 			TranslateMessage(&msg);
 			DispatchMessage(&msg);
-- 
cgit v1.2.3


From 76ab0e277588d8f36e2188a8a67628b74eae50a7 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 24 May 2021 23:41:17 +0300
Subject: SL-15292 waitForChannel crash

---
 indra/newview/llvoicevivox.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 0503ba3f94..0e78e706bd 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -1339,6 +1339,11 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait)
 
                 result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
 
+                if (sShuttingDown)
+                {
+                    break;
+                }
+
                 LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
                 // Don't get confused by prior queued events -- note that it's
                 // very important that mVivoxPump is an LLEventMailDrop, which
@@ -1772,7 +1777,7 @@ bool LLVivoxVoiceClient::waitForChannel()
 
         if (sShuttingDown)
         {
-            logoutOfVivox(true);
+            logoutOfVivox(false);
             return false;
         }
 
@@ -1864,9 +1869,9 @@ bool LLVivoxVoiceClient::waitForChannel()
 
         mIsProcessingChannels = false;
 
-        logoutOfVivox(true);
+        logoutOfVivox(!sShuttingDown /*bool wait*/);
 
-        if (mRelogRequested)
+        if (mRelogRequested && !sShuttingDown)
         {
             LL_DEBUGS("Voice") << "Relog Requested, restarting provisioning" << LL_ENDL;
             if (!provisionVoiceAccount())
-- 
cgit v1.2.3


From c6b1aca74fab532a6e8cdb731cae8d9ea9c1b0bc Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 16 Jun 2021 21:35:11 +0300
Subject: SL-15406 Removed text below initial login screen screenshots

---
 .../skins/default/xui/en/panel_login_first.xml     | 26 ----------------------
 1 file changed, 26 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml
index 726e713595..5568ccb792 100644
--- a/indra/newview/skins/default/xui/en/panel_login_first.xml
+++ b/indra/newview/skins/default/xui/en/panel_login_first.xml
@@ -234,32 +234,6 @@
             left_pad="32"
             name="image_right"
             top="0" />
-          <text
-            follows="left|top"
-            font="SansSerifLarge"
-            text_color="White"
-            height="64"
-            name="image_caption_left"
-            left="0"
-            halign="center"
-            top="408"
-            word_wrap="true"
-            width="400">
-            Your first step is Learning Island. Find the exit portal!
-          </text>
-          <text
-            follows="left|top"
-            font="SansSerifLarge"
-            text_color="White"
-            height="64"
-            name="image_caption_right"
-            left="432"
-            halign="center"
-            top="408"
-            word_wrap="true"
-            width="400">
-            Then explore Social Island and meet other new residents!
-          </text>
         </layout_panel>
         <layout_panel
           height="100"
-- 
cgit v1.2.3


From 9241a87b6fae9785b9a9557104e5329aefdd70b5 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 23 Jun 2021 18:32:57 +0300
Subject: SL-15292 waitForChannel crash #2

---
 indra/newview/llvoicevivox.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 8dd061728f..c383750f60 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -1583,6 +1583,12 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
     {
         result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, SESSION_JOIN_TIMEOUT, timeoutResult);
 
+        if (sShuttingDown)
+        {
+            mIsJoiningSession = false;
+            return false;
+        }
+
         LL_INFOS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
         if (result.has("session"))
         {
@@ -1821,7 +1827,7 @@ bool LLVivoxVoiceClient::waitForChannel()
                 // the parcel is changed, or we have no pending audio sessions,
                 // so try to request the parcel voice info
                 // if we have the cap, we move to the appropriate state
-                requestParcelVoiceInfo();
+                requestParcelVoiceInfo(); //suspends for http reply
             }
             else if (sessionNeedsRelog(mNextAudioSession))
             {
@@ -1833,7 +1839,7 @@ bool LLVivoxVoiceClient::waitForChannel()
             {
                 sessionStatePtr_t joinSession = mNextAudioSession;
                 mNextAudioSession.reset();
-                if (!runSession(joinSession))
+                if (!runSession(joinSession)) //suspends
                 {
                     LL_DEBUGS("Voice") << "runSession returned false; leaving inner loop" << LL_ENDL;
                     break;
@@ -1848,7 +1854,7 @@ bool LLVivoxVoiceClient::waitForChannel()
                 }
             }
 
-            if (!mNextAudioSession)
+            if (!mNextAudioSession && !sShuttingDown)
             {
                 llcoro::suspendUntilTimeout(1.0);
             }
@@ -1921,7 +1927,12 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
 
     while (mVoiceEnabled && isGatewayRunning() && !mSessionTerminateRequested && !mTuningMode)
     {
-        sendCaptureAndRenderDevices();
+        sendCaptureAndRenderDevices(); // suspends
+        if (mSessionTerminateRequested)
+        {
+            break;
+        }
+
         if (mAudioSession && mAudioSession->mParticipantsChanged)
         {
             mAudioSession->mParticipantsChanged = false;
-- 
cgit v1.2.3


From 7cc5b01ded137769cd798229b72013a364264ded Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 23 Jun 2021 19:15:32 +0300
Subject: SL-15292 waitForChannel crash #3

---
 indra/newview/llvoicevivox.cpp | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index c383750f60..d63a6fb1da 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -698,7 +698,7 @@ void LLVivoxVoiceClient::voiceControlCoro()
 			gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
 			gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
 
-			if (mTuningMode)
+			if (mTuningMode && !sShuttingDown)
             {
                 performMicTuning();
             }
@@ -1272,8 +1272,11 @@ bool LLVivoxVoiceClient::loginToVivox()
 
                 // tell the user there is a problem
                 LL_WARNS("Voice") << "login " << loginresp << " will retry login in " << timeout << " seconds." << LL_ENDL;
-                    
-                llcoro::suspendUntilTimeout(timeout);
+                
+                if (!sShuttingDown)
+                {
+                    llcoro::suspendUntilTimeout(timeout);
+                }
             }
             else if (loginresp == "failed")
             {
@@ -2159,7 +2162,7 @@ bool LLVivoxVoiceClient::performMicTuning()
     mIsInTuningMode = true;
     llcoro::suspend();
 
-    while (mTuningMode)
+    while (mTuningMode && !sShuttingDown)
     {
 
         if (mCaptureDeviceDirty || mRenderDeviceDirty)
@@ -2195,9 +2198,12 @@ bool LLVivoxVoiceClient::performMicTuning()
         tuningCaptureStartSendMessage(1);  // 1-loop, zero, don't loop
 
         //---------------------------------------------------------------------
-        llcoro::suspend();
+        if (!sShuttingDown)
+        {
+            llcoro::suspend();
+        }
 
-        while (mTuningMode && !mCaptureDeviceDirty && !mRenderDeviceDirty)
+        while (mTuningMode && !mCaptureDeviceDirty && !mRenderDeviceDirty && !sShuttingDown)
         {
             // process mic/speaker volume changes
             if (mTuningMicVolumeDirty || mTuningSpeakerVolumeDirty)
@@ -2237,7 +2243,7 @@ bool LLVivoxVoiceClient::performMicTuning()
 
         // transition out of mic tuning
         tuningCaptureStopSendMessage();
-        if (mCaptureDeviceDirty || mRenderDeviceDirty)
+        if ((mCaptureDeviceDirty || mRenderDeviceDirty) && !sShuttingDown)
         {
             llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS);
         }
-- 
cgit v1.2.3


From 9451b50b2b855d6de6cc7141428575c06f46aeb0 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 23 Jun 2021 19:48:45 +0300
Subject: SL-15292 waitForChannel crash #4

---
 indra/newview/llvoicevivox.cpp | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index d63a6fb1da..4d2eac8c09 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -703,7 +703,10 @@ void LLVivoxVoiceClient::voiceControlCoro()
                 performMicTuning();
             }
 
-            waitForChannel(); // this doesn't normally return unless relog is needed or shutting down
+            if (!sShuttingDown)
+            {
+                waitForChannel(); // this doesn't normally return unless relog is needed or shutting down
+            }
     
             LL_DEBUGS("Voice") << "lost channel RelogRequested=" << mRelogRequested << LL_ENDL;            
             endAndDisconnectSession();
@@ -1045,7 +1048,14 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
         {
             F32 timeout = pow(PROVISION_RETRY_TIMEOUT, static_cast<float>(retryCount));
             LL_WARNS("Voice") << "Provision CAP 404.  Retrying in " << timeout << " seconds." << LL_ENDL;
-            llcoro::suspendUntilTimeout(timeout);
+            if (sShuttingDown)
+            {
+                return false;
+            }
+            else
+            {
+                llcoro::suspendUntilTimeout(timeout);
+            }
         }
         else if (!status)
         {
@@ -1275,6 +1285,8 @@ bool LLVivoxVoiceClient::loginToVivox()
                 
                 if (!sShuttingDown)
                 {
+                    // Todo: this is way to long, viewer can get stuck waiting during shutdown
+                    // either make it listen to pump or split in smaller waits with checks for shutdown
                     llcoro::suspendUntilTimeout(timeout);
                 }
             }
-- 
cgit v1.2.3


From abf8c4b364bca97d4295797a14f459d85bef1714 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Thu, 24 Jun 2021 18:37:22 +0300
Subject: SL-10297 windows local build fix

win_crash_logger will be fully removed in D520, for now just fixing local relwithdebinfo build
---
 indra/cmake/bugsplat.cmake       | 7 ++++++-
 indra/newview/viewer_manifest.py | 6 ------
 2 files changed, 6 insertions(+), 7 deletions(-)

(limited to 'indra')

diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake
index 5f5cc51f63..4edc4c59cd 100644
--- a/indra/cmake/bugsplat.cmake
+++ b/indra/cmake/bugsplat.cmake
@@ -1,5 +1,10 @@
 if (INSTALL_PROPRIETARY)
-    set(USE_BUGSPLAT ON  CACHE BOOL "Use the BugSplat crash reporting system")
+    # Note that viewer_manifest.py makes decision based on BUGSPLAT_DB and not USE_BUGSPLAT
+    if (BUGSPLAT_DB)
+        set(USE_BUGSPLAT ON  CACHE BOOL "Use the BugSplat crash reporting system")
+    else (BUGSPLAT_DB)
+        set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system")
+    endif (BUGSPLAT_DB)
 else (INSTALL_PROPRIETARY)
     set(USE_BUGSPLAT OFF CACHE BOOL "Use the BugSplat crash reporting system")
 endif (INSTALL_PROPRIETARY)
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 9f9821b4be..6194328759 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -683,12 +683,6 @@ class WindowsManifest(ViewerManifest):
                 self.path("libvlccore.dll")
                 self.path("plugins/")
 
-        if not self.args.get('bugsplat'): # don't include the win_crash_logger if we are using BugSplat
-            # pull in the crash logger from other projects
-            # tag:"crash-logger" here as a cue to the exporter
-            self.path(src='../win_crash_logger/%s/windows-crash-logger.exe' % self.args['configuration'],
-                      dst="win_crash_logger.exe")
-
         if not self.is_packaging_viewer():
             self.package_file = "copied_deps"    
 
-- 
cgit v1.2.3


From 21f70785d7d8cf5e736ab03a944be575b4f68277 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 30 Jun 2021 23:14:16 +0300
Subject: SL-15434 The 'Add to my Landmarks' star icon is not marked in the Top
 menu bar

---
 indra/newview/lllandmarklist.cpp | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 921b80a667..9106d4e986 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -74,6 +74,16 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
 		{
 			return NULL;
 		}
+
+        if (cb)
+        {
+            // Multiple different sources can request same landmark,
+            // mLoadedCallbackMap is a multimap that allows multiple pairs with same key
+            // Todo: this might need to be improved to not hold identical callbacks multiple times
+            loaded_callback_map_t::value_type vt(asset_uuid, cb);
+            mLoadedCallbackMap.insert(vt);
+        }
+
 	    if ( mWaitList.find(asset_uuid) != mWaitList.end() )
 		{
             // Landmark is sheduled for download, but not requested yet
@@ -89,12 +99,6 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
 				return NULL;
 			}
 		}
-		
-		if (cb)
-		{
-			loaded_callback_map_t::value_type vt(asset_uuid, cb);
-			mLoadedCallbackMap.insert(vt);
-		}
 
         if (mRequestedList.size() > MAX_SIMULTANEOUS_REQUESTS)
         {
-- 
cgit v1.2.3


From efc8b268a2686a86c0975b4b3f67ef821a416d98 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Wed, 30 Jun 2021 23:19:47 +0300
Subject: SL-15434 Change default landmark destination

---
 indra/newview/llfloatercreatelandmark.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index eb93a6a75a..813b7ceec8 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -143,7 +143,7 @@ void LLFloaterCreateLandmark::setLandmarkInfo(const LLUUID &folder_id)
 		mLandmarkTitleEditor->setText(name);
 	}
 
-	LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
+	LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : mLandmarksID);
 }
 
 bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
@@ -202,6 +202,10 @@ void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id)
 	{
 		mFolderCombo->setCurrentByID(folder_id);
 	}
+    else
+    {
+        mFolderCombo->setCurrentByID(mLandmarksID);
+    }
 }
 
 void LLFloaterCreateLandmark::onCreateFolderClicked()
@@ -320,4 +324,4 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items)
 			}
 		}
 	}
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3


From d38866d030868068a9e551aab5dd340538d3b3ba Mon Sep 17 00:00:00 2001
From: Mnikolenko Productengine <mnikolenko@productengine.com>
Date: Thu, 1 Jul 2021 13:42:14 +0300
Subject: SL-15512 Update text in the Favorites Bar and Favorites window

---
 indra/newview/skins/default/xui/en/floater_create_landmark.xml | 2 +-
 indra/newview/skins/default/xui/en/panel_navigation_bar.xml    | 6 +++---
 indra/newview/skins/default/xui/en/strings.xml                 | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/skins/default/xui/en/floater_create_landmark.xml b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
index dcedaceaeb..bba30626b2 100644
--- a/indra/newview/skins/default/xui/en/floater_create_landmark.xml
+++ b/indra/newview/skins/default/xui/en/floater_create_landmark.xml
@@ -49,7 +49,7 @@
      layout="topleft"
      name="folder_label"
      top_pad="10"
-     value="Landmark location:"
+     value="Save this landmark in:"
      width="290" />
     <combo_box
      follows="bottom|left"
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 2dae2649a9..1c9aa1eb83 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -151,7 +151,7 @@
 	         layout="topleft"
            auto_resize="true"
            user_resize="true"
-           min_width="254"
+           min_width="342"
            name="favorites_layout_panel"
            width="342">
            <icon
@@ -198,8 +198,8 @@
              tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!"
              top="13"
 	     valign="bottom"
-             width="205">
-              Your saved locations will appear here.
+             width="290">
+              Places you save to your favorites bar will appear here.
             </label>
               <!-- More button actually is a text box. -->
               <more_button
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index f604a16b0b..d115e09d5b 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2298,7 +2298,7 @@ For AI Character: Get the closest navigable point to the point provided.
 	<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
 	<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>	
 	<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
-	<string name="FavoritesNoMatchingItems">To add a place to your favorites bar, click the star to the right of the location name.</string>
+	<string name="FavoritesNoMatchingItems">To add a place to your favorites, click the star to the right of the location name, then save the landmark to "Favorites bar".</string>
 	<string name="MarketplaceNoListing">You have no listings yet.</string>
 	<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>
 	<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
-- 
cgit v1.2.3


From 35f2b14c1d734382a2184d6d5c0794cb558dcc42 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 13 Jul 2021 00:04:23 +0300
Subject: Revert "SL-15434 Change default landmark destination"

This reverts commit efc8b268a2686a86c0975b4b3f67ef821a416d98.
---
 indra/newview/llfloatercreatelandmark.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index 813b7ceec8..6b1d9306fb 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -143,7 +143,7 @@ void LLFloaterCreateLandmark::setLandmarkInfo(const LLUUID &folder_id)
 		mLandmarkTitleEditor->setText(name);
 	}
 
-	LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : mLandmarksID);
+	LLLandmarkActions::createLandmarkHere(name, "", folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
 }
 
 bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right)
@@ -202,10 +202,6 @@ void LLFloaterCreateLandmark::populateFoldersList(const LLUUID &folder_id)
 	{
 		mFolderCombo->setCurrentByID(folder_id);
 	}
-    else
-    {
-        mFolderCombo->setCurrentByID(mLandmarksID);
-    }
 }
 
 void LLFloaterCreateLandmark::onCreateFolderClicked()
-- 
cgit v1.2.3


From be6066eae218856f7fd74b98968a75e5062fa830 Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Wed, 14 Jul 2021 23:27:32 -0400
Subject: Increment viewer version to 6.4.22 following promotion of DRTVWR-516

---
 indra/newview/VIEWER_VERSION.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra')

diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 22beed373e..a15225fad6 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.21
+6.4.22
-- 
cgit v1.2.3