diff options
| author | Mike <contact@mikelittman.me> | 2026-10-08 06:47:32 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-08 19:47:32 +0800 |
| commit | c538254fbd77df962b627460d863911aa2196988 (patch) | |
| tree | 7ad27e28d217108acb12fb199492550e106c3ea5 /indra/llcommon | |
| parent | 55922ee44aad5824e9b18bba750ec06736c87e62 (diff) | |
Do not recreate destroyed singletons during shutdown (#31)
deleteAll() used to let getInstance() build a replacement, which crashed
when the script-editor server posted a toast after LLUI was gone. Shutdown
now refuses that construction, and notification adds do nothing once the
notification system is gone.
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llsingleton.cpp | 13 | ||||
| -rw-r--r-- | indra/llcommon/llsingleton.h | 17 |
2 files changed, 30 insertions, 0 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 |
