diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 3d27b4a5b548c6e699917e15b6888132e60631e0..f4dba16a944076e5e0cb784573b427323b7738c9 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -42,6 +42,7 @@
 #include "lldiriterator.h"
 #include "v4coloru.h"
 #include "llsdserialize.h"
+#include "llcleanup.h"
 
 // system libraries
 #include <iostream>
@@ -634,7 +635,7 @@ int main(int argc, char** argv)
 	}
 	
 	// Cleanup and exit
-	LLImage::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLImage);
 	if (fast_timer_log_thread)
 	{
 		fast_timer_log_thread->shutdown();
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 1459b9ada2785be76b7a8183123832be4895a2b1..d2d507d676613316a9ac6f174df6259a28417da6 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -178,6 +178,7 @@ set(llcommon_HEADER_FILES
     llmortician.h
     llnametable.h
     llpointer.h
+    llpounceable.h
     llpredicate.h
     llpreprocessor.h
     llpriqueuemap.h
@@ -310,6 +311,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llpounceable "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
   #ADD_BUILD_TEST(llallocator llcommon)
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 5a40845e7d739209255b73b529448b73d2986ccd..2c52b11594b66b165735d2c6cbf4733f974e409e 100755
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -48,6 +48,7 @@
 #include "lleventtimer.h"
 #include "google_breakpad/exception_handler.h"
 #include "stringize.h"
+#include "llcleanup.h"
 
 //
 // Signal handling
@@ -177,7 +178,7 @@ LLApp::~LLApp()
 	
 	if(mExceptionHandler != 0) delete mExceptionHandler;
 
-	LLCommon::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLCommon);
 }
 
 // static
diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h
new file mode 100644
index 0000000000000000000000000000000000000000..8eda9a7fb35205c912958af865834dcad043d05f
--- /dev/null
+++ b/indra/llcommon/llcleanup.h
@@ -0,0 +1,30 @@
+/**
+ * @file   llcleanup.h
+ * @author Nat Goodspeed
+ * @date   2015-05-20
+ * @brief  Mechanism for cleaning up subsystem resources
+ * 
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLCLEANUP_H)
+#define LL_LLCLEANUP_H
+
+#include "llerror.h"
+
+// Instead of directly calling SomeClass::cleanupClass(), use
+// SUBSYSTEM_CLEANUP(SomeClass);
+// This logs the call as well as performing it. That gives us a baseline
+// subsystem shutdown order against which to compare subsequent dynamic
+// shutdown schemes.
+#define SUBSYSTEM_CLEANUP(CLASSNAME)                                    \
+    do {                                                                \
+        LL_INFOS("Cleanup") << "Calling " #CLASSNAME "::cleanupClass()" << LL_ENDL; \
+        CLASSNAME::cleanupClass();                                      \
+    } while (0)
+// Use ancient do { ... } while (0) macro trick to permit a block of
+// statements with the same syntax as a single statement.
+
+#endif /* ! defined(LL_LLCLEANUP_H) */
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 19642b0982f4680f7ea459580fb28566e86d54f5..439ff4e628e965da33163f1592d9b432eb16f331 100755
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -31,6 +31,7 @@
 #include "llthread.h"
 #include "lltrace.h"
 #include "lltracethreadrecorder.h"
+#include "llcleanup.h"
 
 //static
 BOOL LLCommon::sAprInitialized = FALSE;
@@ -63,11 +64,11 @@ void LLCommon::cleanupClass()
 	sMasterThreadRecorder = NULL;
 	LLTrace::set_master_thread_recorder(NULL);
 	LLThreadSafeRefCount::cleanupThreadSafeRefCount();
-	LLTimer::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLTimer);
 	if (sAprInitialized)
 	{
 		ll_cleanup_apr();
 		sAprInitialized = FALSE;
 	}
-	LLMemory::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLMemory);
 }
diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h
new file mode 100644
index 0000000000000000000000000000000000000000..94d508d9173aa9805a5980ccf4161a62cb9d976b
--- /dev/null
+++ b/indra/llcommon/llpounceable.h
@@ -0,0 +1,217 @@
+/**
+ * @file   llpounceable.h
+ * @author Nat Goodspeed
+ * @date   2015-05-22
+ * @brief  LLPounceable is tangentially related to a future: it's a holder for
+ *         a value that may or may not exist yet. Unlike a future, though,
+ *         LLPounceable freely allows reading the held value. (If the held
+ *         type T does not have a distinguished "empty" value, consider using
+ *         LLPounceable<boost::optional<T>>.)
+ *
+ *         LLPounceable::callWhenReady() is this template's claim to fame. It
+ *         allows its caller to "pounce" on the held value as soon as it
+ *         becomes non-empty. Call callWhenReady() with any C++ callable
+ *         accepting T. If the held value is already non-empty, callWhenReady()
+ *         will immediately call the callable with the held value. If the held
+ *         value is empty, though, callWhenReady() will enqueue the callable
+ *         for later. As soon as LLPounceable is assigned a non-empty held
+ *         value, it will flush the queue of deferred callables.
+ *
+ *         Consider a global LLMessageSystem* gMessageSystem. Message system
+ *         initialization happens at a very specific point during viewer
+ *         initialization. Other subsystems want to register callbacks on the
+ *         LLMessageSystem instance as soon as it's initialized, but their own
+ *         initialization may precede that. If we define gMessageSystem to be
+ *         an LLPounceable<LLMessageSystem*>, a subsystem can use
+ *         callWhenReady() to either register immediately (if gMessageSystem
+ *         is already up and runnning) or register as soon as gMessageSystem
+ *         is set with a new, initialized instance.
+ *
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLPOUNCEABLE_H)
+#define LL_LLPOUNCEABLE_H
+
+#include "llsingleton.h"
+#include <boost/call_traits.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/utility/value_init.hpp>
+#include <boost/unordered_map.hpp>
+#include <boost/function.hpp>
+#include <queue>
+
+// Forward declare the user template, since we want to be able to point to it
+// in some of its implementation classes.
+template <typename T, class TAG>
+class LLPounceable;
+
+template <typename T, typename TAG>
+struct LLPounceableTraits
+{
+    // Call callWhenReady() with any callable accepting T.
+    typedef boost::function<void (typename boost::call_traits<T>::param_type)> func_t;
+    // Our actual queue is a simple queue of such callables.
+    typedef std::queue<func_t> queue_t;
+    // owner pointer type
+    typedef LLPounceable<T, TAG>* owner_ptr;
+};
+
+// Tag types distinguish the two different implementations of LLPounceable's
+// queue.
+struct LLPounceableQueue {};
+struct LLPounceableStatic {};
+
+// generic LLPounceableQueueImpl deliberately omitted: only the above tags are
+// legal
+template <typename T, class TAG>
+class LLPounceableQueueImpl;
+
+// The implementation selected by LLPounceableStatic uses an LLSingleton
+// because we can't count on a data member queue being initialized at the time
+// we start getting callWhenReady() calls. This is that LLSingleton.
+template <typename T>
+class LLPounceableQueueSingleton:
+    public LLSingleton<LLPounceableQueueSingleton<T> >
+{
+private:
+    typedef LLPounceableTraits<T, LLPounceableStatic> traits;
+    typedef typename traits::owner_ptr owner_ptr;
+    typedef typename traits::queue_t queue_t;
+
+    // For a given held type T, every LLPounceable<T, LLPounceableStatic>
+    // instance will call on the SAME LLPounceableQueueSingleton instance --
+    // given how class statics work. We must keep a separate queue for each
+    // LLPounceable instance. Use a hash map for that.
+    typedef boost::unordered_map<owner_ptr, queue_t> map_t;
+
+public:
+    // Disambiguate queues belonging to different LLPounceables.
+    queue_t& get(owner_ptr owner)
+    {
+        // operator[] has find-or-create semantics -- just what we want!
+        return mMap[owner];
+    }
+
+private:
+    map_t mMap;
+};
+
+// LLPounceableQueueImpl that uses the above LLSingleton
+template <typename T>
+class LLPounceableQueueImpl<T, LLPounceableStatic>
+{
+public:
+    typedef LLPounceableTraits<T, LLPounceableStatic> traits;
+    typedef typename traits::owner_ptr owner_ptr;
+    typedef typename traits::queue_t queue_t;
+
+    queue_t& get(owner_ptr owner) const
+    {
+        // this Impl contains nothing; it delegates to the Singleton
+        return LLPounceableQueueSingleton<T>::instance().get(owner);
+    }
+};
+
+// The implementation selected by LLPounceableQueue directly contains the
+// queue of interest, suitable for an LLPounceable we can trust to be fully
+// initialized when it starts getting callWhenReady() calls.
+template <typename T>
+class LLPounceableQueueImpl<T, LLPounceableQueue>
+{
+public:
+    typedef LLPounceableTraits<T, LLPounceableQueue> traits;
+    typedef typename traits::owner_ptr owner_ptr;
+    typedef typename traits::queue_t queue_t;
+
+    queue_t& get(owner_ptr)
+    {
+        return mQueue;
+    }
+
+private:
+    queue_t mQueue;
+};
+
+// LLPounceable<T> is for an LLPounceable instance on the heap or the stack.
+// LLPounceable<T, LLPounceableStatic> is for a static LLPounceable instance.
+template <typename T, class TAG=LLPounceableQueue>
+class LLPounceable
+{
+private:
+    typedef LLPounceableTraits<T, TAG> traits;
+    typedef typename traits::owner_ptr owner_ptr;
+    typedef typename traits::queue_t queue_t;
+
+public:
+    typedef typename traits::func_t func_t;
+
+    // By default, both the initial value and the distinguished empty value
+    // are a default-constructed T instance. However you can explicitly
+    // specify each.
+    LLPounceable(typename boost::call_traits<T>::value_type init =boost::value_initialized<T>(),
+                 typename boost::call_traits<T>::param_type empty=boost::value_initialized<T>()):
+        mHeld(init),
+        mEmpty(empty)
+    {}
+
+    // make read access to mHeld as cheap and transparent as possible
+    operator T () const { return mHeld; }
+    typename boost::remove_pointer<T>::type operator*() const { return *mHeld; }
+    typename boost::call_traits<T>::value_type operator->() const { return mHeld; }
+    // uncomment 'explicit' as soon as we allow C++11 compilation
+    /*explicit*/ operator bool() const { return bool(mHeld); }
+    bool operator!() const { return ! mHeld; }
+
+    // support both assignment (dumb ptr idiom) and reset() (smart ptr)
+    void operator=(typename boost::call_traits<T>::param_type value)
+    {
+        reset(value);
+    }
+
+    void reset(typename boost::call_traits<T>::param_type value)
+    {
+        mHeld = value;
+        // If this new value is non-empty, flush anything pending in the queue.
+        if (mHeld != mEmpty)
+        {
+            queue_t& queue(get_queue());
+            while (! queue.empty())
+            {
+                queue.front()(mHeld);
+                queue.pop();
+            }
+        }
+    }
+
+    // our claim to fame
+    void callWhenReady(const func_t& func)
+    {
+        if (mHeld != mEmpty)
+        {
+            // If the held value is already non-empty, immediately call func()
+            func(mHeld);
+        }
+        else
+        {
+            // held value still empty, queue func() for later
+            get_queue().push(func);
+        }
+    }
+
+private:
+    queue_t& get_queue() { return mQueue.get(this); }
+
+    // Store both the current and the empty value.
+    // MAYBE: Might be useful to delegate to LLPounceableTraits the meaning of
+    // testing for "empty." For some types we want operator!(); for others we
+    // want to compare to a distinguished value.
+    typename boost::call_traits<T>::value_type mHeld, mEmpty;
+    // This might either contain the queue (LLPounceableQueue) or delegate to
+    // an LLSingleton (LLPounceableStatic).
+    LLPounceableQueueImpl<T, TAG> mQueue;
+};
+
+#endif /* ! defined(LL_LLPOUNCEABLE_H) */
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 29950c108dbe104a54f5eb42e41583e25cb8787e..fde729f8f93e0655fc3233c287637fb828175458 100755
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -269,7 +269,7 @@ class LLRegistrySingleton
 
 		~ScopedRegistrar()
 		{
-			if (!singleton_t::destroyed())
+			if (singleton_t::instanceExists())
 			{
 				popScope();
 			}
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 6e6291a1653c97ac014a4913b937747898697542..a4877eed1f648815be56e4fb194ab26fe105f8c9 100755
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -166,31 +166,19 @@ class LLSingleton : private boost::noncopyable
 		return NULL;
 	}
 
-	static DERIVED_TYPE* getIfExists()
-	{
-		return sData.mInstance;
-	}
-
 	// Reference version of getInstance()
 	// Preferred over getInstance() as it disallows checking for NULL
 	static DERIVED_TYPE& instance()
 	{
 		return *getInstance();
 	}
-	
-	// Has this singleton been created uet?
-	// Use this to avoid accessing singletons before the can safely be constructed
+
+	// Has this singleton been created yet?
+	// Use this to avoid accessing singletons before they can safely be constructed.
 	static bool instanceExists()
 	{
 		return sData.mInitState == INITIALIZED;
 	}
-	
-	// Has this singleton already been deleted?
-	// Use this to avoid accessing singletons from a static object's destructor
-	static bool destroyed()
-	{
-		return sData.mInitState == DELETED;
-	}
 
 private:
 
diff --git a/indra/llcommon/tests/llpounceable_test.cpp b/indra/llcommon/tests/llpounceable_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1f8cdca145f319b35057484ff5a72248da65c939
--- /dev/null
+++ b/indra/llcommon/tests/llpounceable_test.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file   llpounceable_test.cpp
+ * @author Nat Goodspeed
+ * @date   2015-05-22
+ * @brief  Test for llpounceable.
+ * 
+ * $LicenseInfo:firstyear=2015&license=viewerlgpl$
+ * Copyright (c) 2015, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llpounceable.h"
+// STL headers
+// std headers
+// external library headers
+#include <boost/bind.hpp>
+// other Linden headers
+#include "../test/lltut.h"
+
+struct Data
+{
+    Data(const std::string& data):
+        mData(data)
+    {}
+    const std::string mData;
+};
+
+void setter(Data** dest, Data* ptr)
+{
+    *dest = ptr;
+}
+
+static Data* static_check = 0;
+
+// Set up an extern pointer to an LLPounceableStatic so the linker will fill
+// in the forward reference from below, before runtime.
+extern LLPounceable<Data*, LLPounceableStatic> gForward;
+
+struct EnqueueCall
+{
+    EnqueueCall()
+    {
+        // Intentionally use a forward reference to an LLPounceableStatic that
+        // we believe is NOT YET CONSTRUCTED. This models the scenario in
+        // which a constructor in another translation unit runs before
+        // constructors in this one. We very specifically want callWhenReady()
+        // to work even in that case: we need the LLPounceableQueueImpl to be
+        // initialized even if the LLPounceable itself is not.
+        gForward.callWhenReady(boost::bind(setter, &static_check, _1));
+    }
+} nqcall;
+// When this declaration is processed, we should enqueue the
+// setter(&static_check, _1) call for when gForward is set non-NULL. Needless
+// to remark, we want this call not to crash.
+
+// Now declare gForward. Its constructor should not run until after nqcall's.
+LLPounceable<Data*, LLPounceableStatic> gForward;
+
+/*****************************************************************************
+*   TUT
+*****************************************************************************/
+namespace tut
+{
+    struct llpounceable_data
+    {
+    };
+    typedef test_group<llpounceable_data> llpounceable_group;
+    typedef llpounceable_group::object object;
+    llpounceable_group llpounceablegrp("llpounceable");
+
+    template<> template<>
+    void object::test<1>()
+    {
+        set_test_name("LLPounceableStatic out-of-order test");
+        // LLPounceable<T, LLPounceableStatic>::callWhenReady() must work even
+        // before LLPounceable's constructor runs. That's the whole point of
+        // implementing it with an LLSingleton queue. This models (say)
+        // LLPounceableStatic<LLMessageSystem*, LLPounceableStatic>.
+        ensure("static_check should still be null", ! static_check);
+        Data myData("test<1>");
+        gForward = &myData;         // should run setter
+        ensure_equals("static_check should be &myData", static_check, &myData);
+    }
+
+    template<> template<>
+    void object::test<2>()
+    {
+        set_test_name("LLPounceableQueue different queues");
+        // We expect that LLPounceable<T, LLPounceableQueue> should have
+        // different queues because that specialization stores the queue
+        // directly in the LLPounceable instance.
+        Data *aptr = 0, *bptr = 0;
+        LLPounceable<Data*> a, b;
+        a.callWhenReady(boost::bind(setter, &aptr, _1));
+        b.callWhenReady(boost::bind(setter, &bptr, _1));
+        ensure("aptr should be null", ! aptr);
+        ensure("bptr should be null", ! bptr);
+        Data adata("a"), bdata("b");
+        a = &adata;
+        ensure_equals("aptr should be &adata", aptr, &adata);
+        // but we haven't yet set b
+        ensure("bptr should still be null", !bptr);
+        b = &bdata;
+        ensure_equals("bptr should be &bdata", bptr, &bdata);
+    }
+
+    template<> template<>
+    void object::test<3>()
+    {
+        set_test_name("LLPounceableStatic different queues");
+        // LLPounceable<T, LLPounceableStatic> should also have a distinct
+        // queue for each instance, but that engages an additional map lookup
+        // because there's only one LLSingleton for each T.
+        Data *aptr = 0, *bptr = 0;
+        LLPounceable<Data*, LLPounceableStatic> a, b;
+        a.callWhenReady(boost::bind(setter, &aptr, _1));
+        b.callWhenReady(boost::bind(setter, &bptr, _1));
+        ensure("aptr should be null", ! aptr);
+        ensure("bptr should be null", ! bptr);
+        Data adata("a"), bdata("b");
+        a = &adata;
+        ensure_equals("aptr should be &adata", aptr, &adata);
+        // but we haven't yet set b
+        ensure("bptr should still be null", !bptr);
+        b = &bdata;
+        ensure_equals("bptr should be &bdata", bptr, &bdata);
+    }
+
+    template<> template<>
+    void object::test<4>()
+    {
+        set_test_name("LLPounceable<T> looks like T");
+        // We want LLPounceable<T, TAG> to be drop-in replaceable for a plain
+        // T for read constructs. In particular, it should behave like a dumb
+        // pointer -- and with zero abstraction cost for such usage.
+        Data* aptr = 0;
+        Data a("a");
+        // should be able to initialize a pounceable (when its constructor
+        // runs)
+        LLPounceable<Data*> pounceable = &a;
+        // should be able to pass LLPounceable<T> to function accepting T
+        setter(&aptr, pounceable);
+        ensure_equals("aptr should be &a", aptr, &a);
+        // should be able to dereference with *
+        ensure_equals("deref with *", (*pounceable).mData, "a");
+        // should be able to dereference with ->
+        ensure_equals("deref with ->", pounceable->mData, "a");
+        // bool operations
+        ensure("test with operator bool()", pounceable);
+        ensure("test with operator !()", ! (! pounceable));
+    }
+
+    template<> template<>
+    void object::test<5>()
+    {
+        set_test_name("Multiple callWhenReady() queue items");
+        Data *p1 = 0, *p2 = 0, *p3 = 0;
+        Data a("a");
+        LLPounceable<Data*> pounceable;
+        // queue up a couple setter() calls for later
+        pounceable.callWhenReady(boost::bind(setter, &p1, _1));
+        pounceable.callWhenReady(boost::bind(setter, &p2, _1));
+        // should still be pending
+        ensure("p1 should be null", !p1);
+        ensure("p2 should be null", !p2);
+        ensure("p3 should be null", !p3);
+        pounceable = 0;
+        // assigning a new empty value shouldn't flush the queue
+        ensure("p1 should still be null", !p1);
+        ensure("p2 should still be null", !p2);
+        ensure("p3 should still be null", !p3);
+        // using whichever syntax
+        pounceable.reset(0);
+        // try to make ensure messages distinct... tough to pin down which
+        // ensure() failed if multiple ensure() calls in the same test<n> have
+        // the same message!
+        ensure("p1 should again be null", !p1);
+        ensure("p2 should again be null", !p2);
+        ensure("p3 should again be null", !p3);
+        pounceable.reset(&a);       // should flush queue
+        ensure_equals("p1 should be &a", p1, &a);
+        ensure_equals("p2 should be &a", p2, &a);
+        ensure("p3 still not set", !p3);
+        // immediate call
+        pounceable.callWhenReady(boost::bind(setter, &p3, _1));
+        ensure_equals("p3 should be &a", p3, &a);
+    }
+
+    template<> template<>
+    void object::test<6>()
+    {
+        set_test_name("compile-fail test, uncomment to check");
+        // The following declaration should fail: only LLPounceableQueue and
+        // LLPounceableStatic should work as tags.
+//      LLPounceable<Data*, int> pounceable;
+    }
+} // namespace tut
diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
index 385289aefef69b16997148840929fe7b94963c3f..bed436283a501dc9e0ce0a1d2dfbd092bd894e1b 100755
--- a/indra/llcommon/tests/llsingleton_test.cpp
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -65,7 +65,6 @@ namespace tut
 
 		//Delete the instance
 		LLSingletonTest::deleteSingleton();
-		ensure(LLSingletonTest::destroyed());
 		ensure(!LLSingletonTest::instanceExists());
 
 		//Construct it again.
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index e863ddd13ff75939d3cf4aa4988b065ae79983ed..19a20e663ccc12137c0c05c775f5271efd28a217 100755
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -46,6 +46,7 @@
 #include "test_httprequestqueue.hpp"
 
 #include "llproxy.h"
+#include "llcleanup.h"
 
 unsigned long ssl_thread_id_callback(void);
 void ssl_locking_callback(int mode, int type, const char * file, int line);
@@ -101,7 +102,7 @@ void init_curl()
 
 void term_curl()
 {
-	LLProxy::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLProxy);
 	
 	CRYPTO_set_locking_callback(NULL);
 	for (int i(0); i < ssl_mutex_count; ++i)
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index 7a97c16ea7048c6a0b1c86ccc64352795f2b8c7b..0d239c9435a2de969e9ea8dec71f02586e47044c 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -45,6 +45,7 @@
 #include "llhttpclient.h"
 #include "llsdserialize.h"
 #include "llproxy.h"
+#include "llcleanup.h"
  
 LLPumpIO* gServicePump = NULL;
 BOOL gBreak = false;
@@ -587,5 +588,5 @@ bool LLCrashLogger::init()
 void LLCrashLogger::commonCleanup()
 {
 	LLError::logToFile("");   //close crashreport.log
-	LLProxy::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLProxy);
 }
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index e9ce94ab3b62c1f97a404b7ac4d03cc0488bee39..3c3683f12a6a8691893f34bce8a2f9225206ce24 100755
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -77,6 +77,7 @@
 #include "v3math.h"
 #include "v4math.h"
 #include "lltransfertargetvfile.h"
+#include "llpounceable.h"
 
 // Constants
 //const char* MESSAGE_LOG_FILENAME = "message.log";
@@ -1776,7 +1777,9 @@ std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
 	return s;
 }
 
-LLMessageSystem	*gMessageSystem = NULL;
+// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
+// callback registrations for when gMessageSystem is first assigned
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 
 // update appropriate ping info
 void	process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
@@ -2693,7 +2696,7 @@ void end_messaging_system(bool print_summary)
 			LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
 		}
 
-		delete gMessageSystem;
+		delete static_cast<LLMessageSystem*>(gMessageSystem);
 		gMessageSystem = NULL;
 	}
 }
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 348b09b9923bbde5fe023c4d2df7a478af0969e5..a6fabf2126ecc39a3697bed103c6fe0f73d8dc35 100755
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -60,6 +60,7 @@
 #include "llmessagesenderinterface.h"
 
 #include "llstoredmessage.h"
+#include "llpounceable.h"
 
 const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
 const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
@@ -830,7 +831,7 @@ class LLMessageSystem : public LLMessageSenderInterface
 
 
 // external hook into messaging system
-extern LLMessageSystem	*gMessageSystem;
+extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 
 // Must specific overall system version, which is used to determine
 // if a patch is available in the message template checksum verification.
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index a32bfa59ce8d046bf443c85d1e49cbd519e3a0d3..9356a14f1f89fd24a5ee6bc0047bf763c4744002 100755
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -42,6 +42,7 @@
 
 #include "lliosocket.h"
 #include "stringize.h"
+#include "llcleanup.h"
 
 namespace tut
 {
@@ -66,7 +67,7 @@ namespace tut
 		~HTTPClientTestData()
 		{
 			delete mClientPump;
-			LLProxy::cleanupClass();
+			SUBSYSTEM_CLEANUP(LLProxy);
 			apr_pool_destroy(mPool);
 		}
 
diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
index 3b04530c1ac9e5bd98e596a4e9360c144a9f6d09..e20f61b73f8fddadfff14eaf397907ec8bc162e0 100755
--- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
+++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
@@ -31,11 +31,12 @@
 #include "llhost.h"
 #include "message.h"
 #include "llsd.h"
+#include "llpounceable.h"
 
 #include "llhost.cpp" // Needed for copy operator
 #include "net.cpp" // Needed by LLHost.
 
-LLMessageSystem * gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 
 // sensor test doubles
 bool gClearRecvWasCalled = false;
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index 55748ad27e36d2c4fc0c34fea63bea8bd6995f09..41f982a7e22668c70f5312e74967e64dddd1d210 100755
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -33,8 +33,9 @@
 #include "message.h"
 #include "llmessageconfig.h"
 #include "llhttpnode_stub.cpp"
+#include "llpounceable.h"
 
-LLMessageSystem* gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 
 LLMessageConfig::SenderTrust
 LLMessageConfig::getSenderTrustedness(const std::string& msg_name)
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index aabc7ed2e423b61fc6cbff0a63b7f5cfeb4fd121..cc186f4997393e41e9fd9c086c6754fd223f3137 100755
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -60,6 +60,7 @@
 #include "llflyoutbutton.h"
 #include "llsearcheditor.h"
 #include "lltoolbar.h"
+#include "llcleanup.h"
 
 // for XUIParse
 #include "llquaternion.h"
@@ -208,7 +209,7 @@ void LLUI::initClass(const settings_map_t& settings,
 
 void LLUI::cleanupClass()
 {
-	LLRender2D::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLRender2D);
 }
 
 void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup,  const clear_popups_t& clear_popups)
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index 5d3f9ac327be6352eeb877da19519ddc0dac443c..d28f601009a8d2b75dee847b89093e0014f52ff2 100755
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -31,6 +31,7 @@
 #include "llcachename.h"
 #include "lluuid.h"
 #include "message.h"
+#include "llpounceable.h"
 
 #include <string>
 
@@ -167,7 +168,7 @@ char const* const _PREHASH_AgentID = (char *)"AgentID";
 
 LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS);
 
-LLMessageSystem* gMessageSystem = NULL;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 
 //
 // Stub implementation for LLMessageSystem
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l
index 7772c95609269cc3a19c64749ef630a776fc15d2..d5c71d9987d5ebffcd4bb6e90c4002d1789e59ff 100755
--- a/indra/lscript/lscript_compile/indra.l
+++ b/indra/lscript/lscript_compile/indra.l
@@ -102,7 +102,7 @@ int yyerror(const char *fmt, ...);
 "event"				{ count(); return(EVENT); }
 "jump"				{ count(); return(JUMP); }
 "return"			{ count(); return(RETURN); }
-"if"				{ count(); return(IF); }
+"if"				{ count(); return(IFF); }
 "else"				{ count(); return(ELSE); }
 "for"				{ count(); return(FOR); }
 "do"				{ count(); return(DO); }
diff --git a/indra/lscript/lscript_compile/indra.y b/indra/lscript/lscript_compile/indra.y
index a0a034d21c2251a9035825f72e2781c80ced719c..604b5b6b9208ca35736043ac5f53db548bf23b84 100755
--- a/indra/lscript/lscript_compile/indra.y
+++ b/indra/lscript/lscript_compile/indra.y
@@ -117,7 +117,7 @@
 %token					SHIFT_LEFT
 %token					SHIFT_RIGHT
 
-%token					IF
+%token					IFF         /* IF used by a helper library */
 %token					ELSE
 %token					FOR
 %token					DO
@@ -1312,13 +1312,13 @@ statement
 	{ 
 		$$ = $1;
 	}
-	| IF '(' expression ')' statement	%prec LOWER_THAN_ELSE			
+	| IFF '(' expression ')' statement	%prec LOWER_THAN_ELSE			
 	{  
 		$$ = new LLScriptIf(gLine, gColumn, $3, $5);
 		$5->mAllowDeclarations = FALSE;
 		gAllocationManager->addAllocation($$);
 	}
-	| IF '(' expression ')' statement ELSE statement					
+	| IFF '(' expression ')' statement ELSE statement					
 	{  
 		$$ = new LLScriptIfElse(gLine, gColumn, $3, $5, $7);
 		$5->mAllowDeclarations = FALSE;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6dc71bc94e3bf00c4f8a174ab2d506e260658ea5..6a64f67f9c1a944a7a4af8c68ea8c0af3173be45 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -226,6 +226,7 @@
 #include "llsecapi.h"
 #include "llmachineid.h"
 #include "llmainlooprepeater.h"
+#include "llcleanup.h"
 
 
 #include "llviewereventrecorder.h"
@@ -1764,7 +1765,7 @@ bool LLAppViewer::cleanup()
 	gTransferManager.cleanup();
 #endif
 
-	LLLocalBitmapMgr::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLLocalBitmapMgr);
 
 	// Note: this is where gWorldMap used to be deleted.
 
@@ -1872,11 +1873,11 @@ bool LLAppViewer::cleanup()
 	
 	LLViewerObject::cleanupVOClasses();
 
-	LLAvatarAppearance::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLAvatarAppearance);
 	
-	LLAvatarAppearance::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLAvatarAppearance);
 	
-	LLPostProcess::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLPostProcess);
 
 	LLTracker::cleanupInstance();
 	
@@ -1902,12 +1903,12 @@ bool LLAppViewer::cleanup()
 
  	//end_messaging_system();
 
-	LLFollowCamMgr::cleanupClass();
-	//LLVolumeMgr::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLFollowCamMgr);
+	//SUBSYSTEM_CLEANUP(LLVolumeMgr);
 	LLPrimitive::cleanupVolumeManager();
-	LLWorldMapView::cleanupClass();
-	LLFolderViewItem::cleanupClass();
-	LLUI::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLWorldMapView);
+	SUBSYSTEM_CLEANUP(LLFolderViewItem);
+	SUBSYSTEM_CLEANUP(LLUI);
 	
 	//
 	// Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
@@ -1916,7 +1917,7 @@ bool LLAppViewer::cleanup()
 
 	//
 	LL_INFOS() << "Cleaning up VFS" << LL_ENDL;
-	LLVFile::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLVFile);
 
 	LL_INFOS() << "Saving Data" << LL_ENDL;
 	
@@ -2020,7 +2021,7 @@ bool LLAppViewer::cleanup()
 
 	// *NOTE:Mani - The following call is not thread safe. 
 	LL_CHECK_MEMORY
-	LLCurl::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLCurl);
 	LL_CHECK_MEMORY
 
 	// Non-LLCurl libcurl library
@@ -2029,9 +2030,9 @@ bool LLAppViewer::cleanup()
 	// NOTE The following call is not thread safe. 
 	ll_cleanup_ares();
 
-	LLFilePickerThread::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLFilePickerThread);
 
-	//MUST happen AFTER LLCurl::cleanupClass
+	//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
 	delete sTextureCache;
     sTextureCache = NULL;
 	delete sTextureFetch;
@@ -2060,17 +2061,17 @@ bool LLAppViewer::cleanup()
 	LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL;
 
 	//Note:
-	//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
+	//SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown()
 	//because some new image might be generated during cleaning up media. --bao
-	LLViewerMedia::cleanupClass();
-	LLViewerParcelMedia::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLViewerMedia);
+	SUBSYSTEM_CLEANUP(LLViewerParcelMedia);
 	gTextureList.shutdown(); // shutdown again in case a callback added something
 	LLUIImageList::getInstance()->cleanUp();
 	
 	// This should eventually be done in LLAppViewer
-	LLImage::cleanupClass();
-	LLVFSThread::cleanupClass();
-	LLLFSThread::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLImage);
+	SUBSYSTEM_CLEANUP(LLVFSThread);
+	SUBSYSTEM_CLEANUP(LLLFSThread);
 
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	LL_INFOS() << "Auditing VFS" << LL_ENDL;
@@ -2113,9 +2114,9 @@ bool LLAppViewer::cleanup()
 		LL_INFOS() << "File launched." << LL_ENDL;
 	}
 	LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
-	LLProxy::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLProxy);
 
-	LLWearableType::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLWearableType);
 
 	LLMainLoopRepeater::instance().stop();
 
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index ab57e8c170a8b4e43ddd26fb75803ce5e69d2e53..cacd66aee9cdbb9346c9fbf29fe9487e7e17255b 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -101,7 +101,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer()
 	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());
 	gSavedPerAccountSettings.setBOOL("ConversationsParticipantListCollapsed", !isParticipantListExpanded());
 
-	if (!LLSingleton<LLIMMgr>::destroyed())
+	if (LLIMMgr::instanceExists())
 	{
 		LLIMMgr::getInstance()->removeSessionObserver(this);
 	}
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 65ac11092c5d8bd3fa6f0c6e31742ee862f9ab0e..681203ef4f0fa6f0da7c407a0aa3902aafe2efc7 100755
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -152,7 +152,7 @@ LLMuteList* LLMuteList::getInstance()
 {
 	// Register callbacks at the first time that we find that the message system has been created.
 	static BOOL registered = FALSE;
-	if( !registered && gMessageSystem != NULL)
+	if( !registered && gMessageSystem)
 	{
 		registered = TRUE;
 		// Register our various callbacks
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 42fc3001877d6456f9c527403bbedce6550e7fbb..3a85468bdad4cde51b2ba488966c68ddcb29e482 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -194,6 +194,7 @@
 #include "llevents.h"
 #include "llstartuplistener.h"
 #include "lltoolbarview.h"
+#include "llcleanup.h"
 
 #if LL_WINDOWS
 #include "lldxhardware.h"
@@ -2826,7 +2827,7 @@ void LLStartUp::initNameCache()
 
 void LLStartUp::cleanupNameCache()
 {
-	LLAvatarNameCache::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLAvatarNameCache);
 
 	delete gCacheName;
 	gCacheName = NULL;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 3b0adcf7f4cdb4af4c8ed31ad5de94d1504e3092..e7c93926d78ccf8341adc4bbc320adec137ccb36 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -130,6 +130,7 @@
 #include "llpathfindingmanager.h"
 #include "llstartup.h"
 #include "boost/unordered_map.hpp"
+#include "llcleanup.h"
 
 using namespace LLAvatarAppearanceDefines;
 
@@ -8416,7 +8417,7 @@ class LLWorldPostProcess : public view_listener_t
 
 void handle_flush_name_caches()
 {
-	LLAvatarNameCache::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLAvatarNameCache);
 	if (gCacheName) gCacheName->clear();
 }
 
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a2c0a91ea64017a8c638abfaacf1510253e1c084..f463c620d3851b9b303eec67743be215228a6dc6 100755
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -102,6 +102,7 @@
 #include "llmediaentry.h"
 #include "llfloaterperms.h"
 #include "llvocache.h"
+#include "llcleanup.h"
 
 //#define DEBUG_UPDATE_TYPE
 
@@ -527,11 +528,11 @@ void LLViewerObject::initVOClasses()
 
 void LLViewerObject::cleanupVOClasses()
 {
-	LLVOGrass::cleanupClass();
-	LLVOWater::cleanupClass();
-	LLVOTree::cleanupClass();
-	LLVOAvatar::cleanupClass();
-	LLVOVolume::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLVOGrass);
+	SUBSYSTEM_CLEANUP(LLVOWater);
+	SUBSYSTEM_CLEANUP(LLVOTree);
+	SUBSYSTEM_CLEANUP(LLVOAvatar);
+	SUBSYSTEM_CLEANUP(LLVOVolume);
 
 	sObjectDataMap.clear();
 }
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index e317989f043e56d32173bfdd69e90572c90ad649..12ff88c517941f20f030059afbf41f3b3fb5ff3e 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -208,6 +208,7 @@
 #include "llwindowlistener.h"
 #include "llviewerwindowlistener.h"
 #include "llpaneltopinfobar.h"
+#include "llcleanup.h"
 
 #if LL_WINDOWS
 #include <tchar.h> // For Unicode conversion methods
@@ -2124,7 +2125,7 @@ void LLViewerWindow::shutdownGL()
 	// Shutdown GL cleanly.  Order is very important here.
 	//--------------------------------------------------------
 	LLFontGL::destroyDefaultFonts();
-	LLFontManager::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLFontManager);
 	stop_glerror();
 
 	gSky.cleanup();
@@ -2147,7 +2148,7 @@ void LLViewerWindow::shutdownGL()
 	LLWorldMapView::cleanupTextures();
 
 	LLViewerTextureManager::cleanup() ;
-	LLImageGL::cleanupClass() ;
+	SUBSYSTEM_CLEANUP(LLImageGL) ;
 
 	LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ;
 
@@ -2160,7 +2161,7 @@ void LLViewerWindow::shutdownGL()
 
 	gGL.shutdown();
 
-	LLVertexBuffer::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLVertexBuffer);
 
 	LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ;
 }
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 03712c1065e31c3ed57b6f0682681020e970d690..9c1b78626ff2d504f4dd9740739ec5b78419efd1 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -115,6 +115,7 @@
 #include "llpathfindingpathtool.h"
 #include "llscenemonitor.h"
 #include "llprogressview.h"
+#include "llcleanup.h"
 
 #ifdef _DEBUG
 // Debug indices is disabled for now for debug performance - djs 4/24/02
@@ -7373,7 +7374,7 @@ void LLPipeline::doResetVertexBuffers(bool forced)
 	}
 	LLVOPartGroup::destroyGL();
 
-	LLVertexBuffer::cleanupClass();
+	SUBSYSTEM_CLEANUP(LLVertexBuffer);
 	
 	//delete all name pool caches
 	LLGLNamePool::cleanupPools();
diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp
index c49b0350e9b279925145c3674de7861cbd8a9297..5e3649fdaedb19dfeee0a263e64736f27be634bc 100755
--- a/indra/newview/tests/llremoteparcelrequest_test.cpp
+++ b/indra/newview/tests/llremoteparcelrequest_test.cpp
@@ -33,6 +33,7 @@
 #include "../llagent.h"
 #include "message.h"
 #include "llurlentry.h"
+#include "llpounceable.h"
 
 namespace {
 	const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
@@ -61,7 +62,7 @@ void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
 void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
 void LLMessageSystem::nextBlockFast(char const *) { }
 void LLMessageSystem::newMessage(char const *) { }
-LLMessageSystem * gMessageSystem;
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
 char const* const _PREHASH_AgentID = 0;   // never dereferenced during this test
 char const* const _PREHASH_AgentData = 0; // never dereferenced during this test
 LLAgent gAgent;
diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp
index aa23699de07298dedd615cd8b5c1e60b6f216205..b9c025f518f040c0ee172bea6ff5e2f1daf69702 100755
--- a/indra/test/message_tut.cpp
+++ b/indra/test/message_tut.cpp
@@ -103,7 +103,7 @@ namespace tut
 		~LLMessageSystemTestData()
 		{
 			// not end_messaging_system()
-			delete gMessageSystem;
+			delete static_cast<LLMessageSystem*>(gMessageSystem);
 			gMessageSystem = NULL;
 
 			// rm contents of temp dir