From 1cd65a244736d0c11f5740f8a19f8d5459d5d4b6 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Tue, 25 Aug 2020 22:21:46 +0300
Subject: [PATCH] SL-13498 Crash at ~LLPersistentNotificationChannel

Callstack is clearly broken since it points to LLNotifications::instance().clear(); after 'Goodbye!', my suspicion is that something reinitialized singleton so I fixed cleanup and added some logging to see if there is a dupplicate init
---
 indra/llui/llnotifications.cpp | 32 +++++++++++++++++++-------------
 indra/llui/llnotifications.h   |  2 ++
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 6a7075301be..06ec648178e 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -255,7 +255,7 @@ LLNotificationForm::LLNotificationForm(const LLSD& sd)
 	}
 	else
 	{
-		LL_WARNS() << "Invalid form data " << sd << LL_ENDL;
+		LL_WARNS("Notifications") << "Invalid form data " << sd << LL_ENDL;
 		mFormData = LLSD::emptyArray();
 	}
 }
@@ -448,11 +448,11 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
 		mUniqueContext.push_back(context.value);
 	}
 	
-	LL_DEBUGS() << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL;
+	LL_DEBUGS("Notifications") << "notification \"" << mName << "\": tag count is " << p.tags.size() << LL_ENDL;
 	
 	BOOST_FOREACH(const LLNotificationTemplate::Tag& tag, p.tags)
 	{
-		LL_DEBUGS() << "    tag \"" << std::string(tag.value) << "\"" << LL_ENDL;
+		LL_DEBUGS("Notifications") << "    tag \"" << std::string(tag.value) << "\"" << LL_ENDL;
 		mTags.push_back(tag.value);
 	}
 
@@ -1398,8 +1398,14 @@ void LLNotifications::initSingleton()
 	createDefaultChannels();
 }
 
+void LLNotifications::cleanupSingleton()
+{
+    clear();
+}
+
 void LLNotifications::createDefaultChannels()
 {
+    LL_INFOS("Notifications") << "Generating default notification channels" << LL_ENDL;
 	// now construct the various channels AFTER loading the notifications,
 	// because the history channel is going to rewrite the stored notifications file
 	mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "",
@@ -1455,7 +1461,7 @@ void LLNotifications::forceResponse(const LLNotification::Params& params, S32 op
 	
 	if (selected_item.isUndefined())
 	{
-		LL_WARNS() << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL;
+		LL_WARNS("Notifications") << "Invalid option" << option << " for notification " << (std::string)params.name << LL_ENDL;
 		return;
 	}
 	response[selected_item["name"].asString()] = true;
@@ -1489,12 +1495,12 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
 			if (found != replacements.end())
 			{
 				replacement = found->second;
-				LL_DEBUGS() << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL;
+				LL_DEBUGS("Notifications") << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << LL_ENDL;
 				it->second->setValue(replacement);
 			}
 			else
 			{
-				LL_WARNS() << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL;
+				LL_WARNS("Notifications") << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << LL_ENDL;
 			}
 		}
 	}
@@ -1533,7 +1539,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path
 
 bool LLNotifications::loadTemplates()
 {
-	LL_INFOS() << "Reading notifications template" << LL_ENDL;
+	LL_INFOS("Notifications") << "Reading notifications template" << LL_ENDL;
 	// Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it
 	// output all relevant pathnames instead of just the ones from the most
 	// specific skin.
@@ -1604,7 +1610,7 @@ bool LLNotifications::loadTemplates()
 		mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification));
 	}
 
-	LL_INFOS() << "...done" << LL_ENDL;
+	LL_INFOS("Notifications") << "...done" << LL_ENDL;
 
 	return true;
 }
@@ -1832,7 +1838,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
 	for(it = mVisibilityRules.begin(); it != mVisibilityRules.end(); it++)
 	{
 		// An empty type/tag/name string will match any notification, so only do the comparison when the string is non-empty in the rule.
-		LL_DEBUGS() 
+		LL_DEBUGS("Notifications")
 			<< "notification \"" << n->getName() << "\" " 
 			<< "testing against " << ((*it)->mVisible?"show":"hide") << " rule, "
 			<< "name = \"" << (*it)->mName << "\" "
@@ -1877,7 +1883,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
 			if((*it)->mResponse.empty())
 			{
 				// Response property is empty.  Cancel this notification.
-				LL_DEBUGS() << "cancelling notification " << n->getName() << LL_ENDL;
+				LL_DEBUGS("Notifications") << "cancelling notification " << n->getName() << LL_ENDL;
 
 				cancel(n);
 			}
@@ -1888,7 +1894,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
 				// TODO: verify that the response template has an item with the correct name
 				response[(*it)->mResponse] = true;
 
-				LL_DEBUGS() << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL;
+				LL_DEBUGS("Notifications") << "responding to notification " << n->getName() << " with response = " << response << LL_ENDL;
 				
 				n->respond(response);
 			}
@@ -1900,7 +1906,7 @@ bool LLNotifications::isVisibleByRules(LLNotificationPtr n)
 		break;
 	}
 	
-	LL_DEBUGS() << "allowing notification " << n->getName() << LL_ENDL;
+	LL_DEBUGS("Notifications") << "allowing notification " << n->getName() << LL_ENDL;
 
 	return true;
 }
@@ -1961,7 +1967,7 @@ void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
 	// from PE merge - we should figure out if this is the right thing to do
 	if (name.empty())
 	{
-		LL_WARNS() << "Empty name received for Id: " << agent_id << LL_ENDL;
+		LL_WARNS("Notifications") << "Empty name received for Id: " << agent_id << LL_ENDL;
 		name = SYSTEM_FROM;
 	}
 	
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index cac687f53d8..2f4578da170 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -957,6 +957,7 @@ class LLNotifications :
 	
 private:
 	/*virtual*/ void initSingleton();
+	/*virtual*/ void cleanupSingleton();
 	
 	void loadPersistentNotifications();
 
@@ -1069,6 +1070,7 @@ class LLPersistentNotificationChannel : public LLNotificationChannel
 	LLPersistentNotificationChannel() 
 		:	LLNotificationChannel("Persistent", "Visible", &notificationFilter)
 	{}
+	virtual ~LLPersistentNotificationChannel() {}
 
 	typedef std::vector<LLNotificationPtr> history_list_t;
 	history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); }
-- 
GitLab