diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llsingleton.cpp | 13 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 17 | ||||
| -rw-r--r-- | indra/llui/llnotificationsutil.cpp | 62 | ||||
| -rw-r--r-- | indra/newview/llscripteditorws.cpp | 8 |
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) |
