summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llsingleton.cpp13
-rw-r--r--indra/llcommon/llsingleton.h17
-rw-r--r--indra/llui/llnotificationsutil.cpp62
-rw-r--r--indra/newview/llscripteditorws.cpp8
4 files changed, 92 insertions, 8 deletions
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 05dc3cde79..46659e6b7b 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -27,6 +27,8 @@
#include "linden_common.h"
#include "llsingleton.h"
+#include <atomic>
+
#include "llerror.h"
#include "llerrorcontrol.h"
#include "lldependencies.h"
@@ -406,8 +408,19 @@ void LLSingletonBase::cleanup_()
}
//static
+namespace
+{
+ std::atomic<bool> sShuttingDown{false};
+}
+
+bool LLSingletonBase::shuttingDown()
+{
+ return sShuttingDown.load(std::memory_order_acquire);
+}
+
void LLSingletonBase::deleteAll()
{
+ sShuttingDown.store(true, std::memory_order_release);
// It's essential to traverse these in dependency order.
for (LLSingletonBase* sp : dep_sort())
{
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index ebef2489ce..c088f7a9c4 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -46,6 +46,9 @@ class LLSingletonBase
{
public:
class MasterList;
+ // True once deleteAll() has started. getInstance() must not construct
+ // a replacement for a singleton that shutdown has already destroyed.
+ static bool shuttingDown();
LLSingletonBase(const LLSingletonBase&) = delete;
LLSingletonBase& operator=(const LLSingletonBase&) = delete;
@@ -533,6 +536,13 @@ public:
case DELETED:
// called after deleteSingleton()
+ if (LLSingletonBase::shuttingDown())
+ {
+ logwarns({"Refusing to recreate deleted singleton ",
+ classname<DERIVED_TYPE>(),
+ " during shutdown"});
+ return nullptr;
+ }
logwarns({"Trying to access deleted singleton ",
classname<DERIVED_TYPE>(),
" -- creating new instance"});
@@ -540,6 +550,13 @@ public:
[[fallthrough]];
case UNINITIALIZED:
case QUEUED:
+ if (LLSingletonBase::shuttingDown())
+ {
+ logwarns({"Refusing to construct singleton ",
+ classname<DERIVED_TYPE>(),
+ " during shutdown"});
+ return nullptr;
+ }
// QUEUED means some secondary thread has already requested an
// instance, but for present purposes that's semantically
// identical to UNINITIALIZED: either way, we must ourselves
diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp
index 6b570d043f..ce36f33bf9 100644
--- a/indra/llui/llnotificationsutil.cpp
+++ b/indra/llui/llnotificationsutil.cpp
@@ -30,20 +30,44 @@
#include "llsd.h"
#include "llxmlnode.h" // apparently needed to call LLNotifications::instance()
+namespace
+{
+ // deleteAll() must not resurrect LLNotifications after its dependencies
+ // are gone. A null return means the caller should skip the toast.
+ LLNotifications* live_notifications()
+ {
+ if (LLNotifications::wasDeleted() || LLSingletonBase::shuttingDown())
+ {
+ return nullptr;
+ }
+ return LLNotifications::getInstance();
+ }
+}
+
LLNotificationPtr LLNotificationsUtil::add(const std::string& name)
{
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
LLNotification::Params::Functor functor_p;
functor_p.name = name;
- return LLNotifications::instance().add(
+ return notifications->add(
LLNotification::Params().name(name).substitutions(LLSD()).payload(LLSD()).functor(functor_p));
}
LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
const LLSD& substitutions)
{
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
LLNotification::Params::Functor functor_p;
functor_p.name = name;
- return LLNotifications::instance().add(
+ return notifications->add(
LLNotification::Params().name(name).substitutions(substitutions).payload(LLSD()).functor(functor_p));
}
@@ -51,9 +75,14 @@ LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload)
{
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
LLNotification::Params::Functor functor_p;
functor_p.name = name;
- return LLNotifications::instance().add(
+ return notifications->add(
LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
@@ -62,9 +91,14 @@ LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
const LLSD& payload,
const std::string& functor_name)
{
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
LLNotification::Params::Functor functor_p;
functor_p.name = functor_name;
- return LLNotifications::instance().add(
+ return notifications->add(
LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
@@ -73,9 +107,14 @@ LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
const LLSD& payload,
std::function<void (const LLSD&, const LLSD&)> functor)
{
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
LLNotification::Params::Functor functor_p;
functor_p.function = functor;
- return LLNotifications::instance().add(
+ return notifications->add(
LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
@@ -86,10 +125,19 @@ S32 LLNotificationsUtil::getSelectedOption(const LLSD& notification, const LLSD&
void LLNotificationsUtil::cancel(LLNotificationPtr pNotif)
{
- LLNotifications::instance().cancel(pNotif);
+ LLNotifications* notifications = live_notifications();
+ if (notifications)
+ {
+ notifications->cancel(pNotif);
+ }
}
LLNotificationPtr LLNotificationsUtil::find(LLUUID uuid)
{
- return LLNotifications::instance().find(uuid);
+ LLNotifications* notifications = live_notifications();
+ if (!notifications)
+ {
+ return LLNotificationPtr();
+ }
+ return notifications->find(uuid);
}
diff --git a/indra/newview/llscripteditorws.cpp b/indra/newview/llscripteditorws.cpp
index 0a3e09fec0..1b4babceec 100644
--- a/indra/newview/llscripteditorws.cpp
+++ b/indra/newview/llscripteditorws.cpp
@@ -465,7 +465,13 @@ void LLScriptEditorWSServer::onStopped()
LL_INFOS("ScriptEditorWS") << "Script editor WebSocket server stopped, all state cleaned up" << LL_ENDL;
- LLNotificationsUtil::add("ExternalEditorServerStopped");
+ // Skip the toast during shutdown. cleanup() destroys LLUI before
+ // WebSocket singletons, and constructing this alert crashes in the
+ // already-freed notification tables.
+ if (!LLApp::isExiting())
+ {
+ LLNotificationsUtil::add("ExternalEditorServerStopped");
+ }
}
void LLScriptEditorWSServer::onConnectionOpened(const LLWebsocketMgr::WSConnection::ptr_t& connection)