diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index e6407ecf220b0df466bb3542a745df6c1ab415d8..2ddb3edbdd38e2020936a77d7b780c7cea65872e 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -1067,7 +1067,15 @@ namespace LLError
 		{
 			return false;
 		}
-		
+
+		// If we hit a logging request very late during shutdown processing,
+		// when either of the relevant LLSingletons has already been deleted,
+		// DO NOT resurrect them.
+		if (Settings::wasDeleted() || Globals::wasDeleted())
+		{
+			return false;
+		}
+
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 		
 		s->mShouldLogCallCounter++;
@@ -1106,7 +1114,10 @@ namespace LLError
 	std::ostringstream* Log::out()
 	{
 		LogLock lock;
-		if (lock.ok())
+		// If we hit a logging request very late during shutdown processing,
+		// when either of the relevant LLSingletons has already been deleted,
+		// DO NOT resurrect them.
+		if (lock.ok() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
 		{
 			Globals* g = Globals::getInstance();
 
@@ -1116,41 +1127,49 @@ namespace LLError
 				return &g->messageStream;
 			}
 		}
-		
+
 		return new std::ostringstream;
 	}
-	
+
 	void Log::flush(std::ostringstream* out, char* message)
-    {
-       LogLock lock;
-       if (!lock.ok())
-       {
-           return;
-       }
-       
-	   if(strlen(out->str().c_str()) < 128)
-	   {
-		   strcpy(message, out->str().c_str());
-	   }
-	   else
-	   {
-		   strncpy(message, out->str().c_str(), 127);
-		   message[127] = '\0' ;
-	   }
-	   
-	   Globals* g = Globals::getInstance();
-       if (out == &g->messageStream)
-       {
-           g->messageStream.clear();
-           g->messageStream.str("");
-           g->messageStreamInUse = false;
-       }
-       else
-       {
-           delete out;
-       }
-	   return ;
-    }
+	{
+		LogLock lock;
+		if (!lock.ok())
+		{
+			return;
+		}
+
+		// If we hit a logging request very late during shutdown processing,
+		// when either of the relevant LLSingletons has already been deleted,
+		// DO NOT resurrect them.
+		if (Settings::wasDeleted() || Globals::wasDeleted())
+		{
+			return;
+		}
+
+		if(strlen(out->str().c_str()) < 128)
+		{
+			strcpy(message, out->str().c_str());
+		}
+		else
+		{
+			strncpy(message, out->str().c_str(), 127);
+			message[127] = '\0' ;
+		}
+
+		Globals* g = Globals::getInstance();
+		if (out == &g->messageStream)
+		{
+			g->messageStream.clear();
+			g->messageStream.str("");
+			g->messageStreamInUse = false;
+		}
+		else
+		{
+			delete out;
+		}
+		return ;
+	}
 
 	void Log::flush(std::ostringstream* out, const CallSite& site)
 	{
@@ -1159,7 +1178,15 @@ namespace LLError
 		{
 			return;
 		}
-		
+
+		// If we hit a logging request very late during shutdown processing,
+		// when either of the relevant LLSingletons has already been deleted,
+		// DO NOT resurrect them.
+		if (Settings::wasDeleted() || Globals::wasDeleted())
+		{
+			return;
+		}
+
 		Globals* g = Globals::getInstance();
 		SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
 
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 97270e4931d7cfc7a0b7196173abffd94a62c728..a3856e4fc46b71f6c62a3a4e6bd3e8a057996bdd 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -281,7 +281,8 @@ const std::string LLEventPump::ANONYMOUS = std::string();
 
 LLEventPump::LLEventPump(const std::string& name, bool tweak):
     // Register every new instance with LLEventPumps
-    mName(LLEventPumps::instance().registerNew(*this, name, tweak)),
+    mRegistry(LLEventPumps::instance().getHandle()),
+    mName(mRegistry.get()->registerNew(*this, name, tweak)),
     mSignal(new LLStandardSignal()),
     mEnabled(true)
 {}
@@ -292,8 +293,13 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):
 
 LLEventPump::~LLEventPump()
 {
-    // Unregister this doomed instance from LLEventPumps
-    LLEventPumps::instance().unregister(*this);
+    // Unregister this doomed instance from LLEventPumps -- but only if
+    // LLEventPumps is still around!
+    LLEventPumps* registry = mRegistry.get();
+    if (registry)
+    {
+        registry->unregister(*this);
+    }
 }
 
 // static data member
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 7cff7dfd4537b99d99c0a83f6753c941375b7000..1d51c660ed0d7990c63a4f93c875b2e61597a7f8 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -62,6 +62,7 @@
 #include "lldependencies.h"
 #include "llstl.h"
 #include "llexception.h"
+#include "llhandle.h"
 
 /*==========================================================================*|
 // override this to allow binding free functions with more parameters
@@ -227,7 +228,15 @@ class LLEventPump;
  * LLEventPumps is a Singleton manager through which one typically accesses
  * this subsystem.
  */
-class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
+// LLEventPumps isa LLHandleProvider only for (hopefully rare) long-lived
+// class objects that must refer to this class late in their lifespan, say in
+// the destructor. Specifically, the case that matters is a possible reference
+// after LLEventPumps::deleteSingleton(). (Lingering LLEventPump instances are
+// capable of this.) In that case, instead of calling LLEventPumps::instance()
+// again -- resurrecting the deleted LLSingleton -- store an
+// LLHandle<LLEventPumps> and test it before use.
+class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>,
+                                  public LLHandleProvider<LLEventPumps>
 {
     LLSINGLETON(LLEventPumps);
 public:
@@ -590,6 +599,9 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable
         return this->listen_impl(name, listener, after, before);
     }
 
+    // must precede mName; see LLEventPump::LLEventPump()
+    LLHandle<LLEventPumps> mRegistry;
+
     std::string mName;
 
 protected:
@@ -817,14 +829,14 @@ class LL_COMMON_API LLListenerWrapperBase
         mConnection(new LLBoundListener)
     {
     }
-	
+
     /// Copy constructor. Copy shared_ptrs to original instance data.
     LLListenerWrapperBase(const LLListenerWrapperBase& that):
         mName(that.mName),
         mConnection(that.mConnection)
     {
     }
-	virtual ~LLListenerWrapperBase() {}
+    virtual ~LLListenerWrapperBase() {}
 
     /// Ask LLEventPump::listen() for the listener name
     virtual void accept_name(const std::string& name) const
diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h
index feb5f418489e5b401eff95591ba4dd0fc31dbd66..570cd330b87ff228e33f938da79ef184c1a41f32 100644
--- a/indra/llcommon/llhandle.h
+++ b/indra/llcommon/llhandle.h
@@ -28,6 +28,7 @@
 #define LLHANDLE_H
 
 #include "llpointer.h"
+#include "llrefcount.h"
 #include "llexception.h"
 #include <stdexcept>
 #include <boost/type_traits/is_convertible.hpp>
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 1b915dfd6e96d927fd520ba58415c52387295049..0d4a1f34f8726d511716d52e10fcb05130a43f75 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -452,6 +452,14 @@ class LLSingleton : public LLSingletonBase
         return sData.mInitState == INITIALIZED;
     }
 
+    // Has this singleton been deleted? This can be useful during shutdown
+    // processing to avoid "resurrecting" a singleton we thought we'd already
+    // cleaned up.
+    static bool wasDeleted()
+    {
+        return sData.mInitState == DELETED;
+    }
+
 private:
     struct SingletonData
     {
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b58af54985c59e88543535eee36a05eba0d0a58c..616e0841199b220835baafa3933358ff21d24eea 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -738,10 +738,7 @@ LLAppViewer::LLAppViewer()
 LLAppViewer::~LLAppViewer()
 {
 	delete mSettingsLocationList;
-	LLViewerEventRecorder::deleteSingleton();
 
-	LLLoginInstance::instance().setUpdaterService(0);
-	
 	destroyMainloopTimeout();
     
 	// If we got to this destructor somehow, the app didn't hang.
@@ -2110,6 +2107,10 @@ bool LLAppViewer::cleanup()
 	// realtime, or might throw an exception.
 	LLSingletonBase::cleanupAll();
 
+	// The logging subsystem depends on an LLSingleton. Any logging after
+	// LLSingletonBase::deleteAll() won't be recorded.
+	LL_INFOS() << "Goodbye!" << LL_ENDL;
+
 	// This calls every remaining LLSingleton's deleteSingleton() method.
 	// No class destructor should perform any cleanup that might take
 	// significant realtime, or throw an exception.
@@ -2122,8 +2123,6 @@ bool LLAppViewer::cleanup()
 	// probably useful to be able to log that order.
 	LLSingletonBase::deleteAll();
 
-	LL_INFOS() << "Goodbye!" << LL_ENDL;
-
 	removeDumpDir();
 
 	// return 0;
diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp
index 1665e41e7029546e6b4281807adb6a8d9ad7d731..df021948c347668c948ab9fce08daf8ff386fa11 100644
--- a/indra/viewer_components/updater/llupdaterservice.cpp
+++ b/indra/viewer_components/updater/llupdaterservice.cpp
@@ -158,7 +158,8 @@ class LLUpdaterServiceImpl :
 private:
 	std::string mNewChannel;
 	std::string mNewVersion;
-	
+	LLTempBoundListener mMainLoopConnection;
+
 	void restartTimer(unsigned int seconds);
 	void setState(LLUpdaterService::eUpdaterState state);
 	void stopTimer();
@@ -179,7 +180,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() :
 LLUpdaterServiceImpl::~LLUpdaterServiceImpl()
 {
 	LL_INFOS("UpdaterService") << "shutting down updater service" << LL_ENDL;
-	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+	// Destroying an LLTempBoundListener implicitly disconnects. That's its
+	// whole purpose.
 }
 
 void LLUpdaterServiceImpl::initialize(const std::string&  channel,
@@ -560,7 +562,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)
 	seconds << " seconds" << LL_ENDL; 
 	mTimer.start();
 	mTimer.setTimerExpirySec((F32)seconds);
-	LLEventPumps::instance().obtain("mainloop").listen(
+	mMainLoopConnection = LLEventPumps::instance().obtain("mainloop").listen(
 		sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));
 }
 
@@ -589,7 +591,7 @@ void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state)
 void LLUpdaterServiceImpl::stopTimer()
 {
 	mTimer.stop();
-	LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName);
+	mMainLoopConnection.disconnect();
 }
 
 bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event)