diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 787503a6e424c9534c45384c006f5d0b66cae5d5..f89ab586d53f3ecb5f67645d52bb309590080831 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -637,6 +637,7 @@ LLAppViewer::LLAppViewer()
 	mLogoutMarkerFile(),
 	mReportedCrash(false),
 	mNumSessions(0),
+    mGeneralThreadPool(nullptr),
 	mPurgeCache(false),
 	mPurgeCacheOnExit(false),
 	mPurgeUserDataOnExit(false),
@@ -1712,11 +1713,6 @@ void LLAppViewer::flushLFSIO()
 
 bool LLAppViewer::cleanup()
 {
-	// Since we don't know what functions are going to be queued by
-	// onCleanup(), we have to assume they might rely on some of the things
-	// we're about to destroy below. Run them first.
-	mOnCleanup();
-
     LLAtmosphere::cleanupClass();
 
 	//ditch LLVOAvatarSelf instance
@@ -2070,6 +2066,10 @@ bool LLAppViewer::cleanup()
 	sTextureCache->shutdown();
 	sImageDecodeThread->shutdown();
 	sPurgeDiskCacheThread->shutdown();
+    if (mGeneralThreadPool)
+    {
+        mGeneralThreadPool->close();
+    }
 
 	sTextureFetch->shutDownTextureCacheThread() ;
 	sTextureFetch->shutDownImageDecodeThread() ;
@@ -2094,6 +2094,8 @@ bool LLAppViewer::cleanup()
 	mFastTimerLogThread = NULL;
 	delete sPurgeDiskCacheThread;
 	sPurgeDiskCacheThread = NULL;
+    delete mGeneralThreadPool;
+    mGeneralThreadPool = NULL;
 
 	if (LLFastTimerView::sAnalyzePerformance)
 	{
@@ -2179,6 +2181,24 @@ bool LLAppViewer::cleanup()
 	return true;
 }
 
+void LLAppViewer::initGeneralThread()
+{
+    if (mGeneralThreadPool)
+    {
+        return;
+    }
+
+    LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
+    LLSD sizeSpec{ poolSizes["General"] };
+    LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 };
+    LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
+        << poolSize << " threads" << LL_ENDL;
+    // We don't want anyone, especially the main thread, to have to block
+    // due to this ThreadPool being full.
+    mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024);
+    mGeneralThreadPool->start();
+}
+
 bool LLAppViewer::initThreads()
 {
 	static const bool enable_threads = true;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index d807cf9765e0f60dfe568ca48c0c3af454d1179a..a86fa7d8733de1e5b2347db24b78d772e3378025 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -63,6 +63,11 @@ class LLViewerJoystick;
 class LLPurgeDiskCacheThread;
 class LLViewerRegion;
 
+namespace LL
+{
+    class ThreadPool;
+}
+
 extern LLTrace::BlockTimerStatHandle FTM_FRAME;
 
 class LLAppViewer : public LLApp
@@ -201,13 +206,7 @@ class LLAppViewer : public LLApp
 
 	void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
 
-	typedef boost::signals2::signal<void()> cleanup_signal_t;
-	cleanup_signal_t mOnCleanup;
-	boost::signals2::connection onCleanup(const cleanup_signal_t::slot_type& cb)
-	{
-		return mOnCleanup.connect(cb);
-	}
-
+    void initGeneralThread();
 	void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; }
 	void purgeCache(); // Clear the local cache. 
 	void purgeCacheImmediate(); //clear local cache immediately.
@@ -269,7 +268,6 @@ class LLAppViewer : public LLApp
 	void idle(); 
 	void idleShutdown();
 	// update avatar SLID and display name caches
-	void idleExperienceCache();
 	void idleNameCache();
 	void idleNetwork();
 
@@ -298,6 +296,7 @@ class LLAppViewer : public LLApp
 	static LLImageDecodeThread* sImageDecodeThread; 
 	static LLTextureFetch* sTextureFetch;
 	static LLPurgeDiskCacheThread* sPurgeDiskCacheThread;
+    LL::ThreadPool* mGeneralThreadPool;
 
 	S32 mNumSessions;
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9782881f0e92f2048d72b747e0f7a6aa3b06b9b0..8912d1cff16099d7803f4c6586efc1c87799a7af 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1496,19 +1496,7 @@ bool idle_startup()
 		display_startup();
 
 		// start up the ThreadPool we'll use for textures et al.
-		{
-			LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
-			LLSD sizeSpec{ poolSizes["General"] };
-			LLSD::Integer poolSize{ sizeSpec.isInteger()? sizeSpec.asInteger() : 3 };
-			LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
-									<< poolSize << " threads" << LL_ENDL;
-			// We don't want anyone, especially the main thread, to have to block
-			// due to this ThreadPool being full.
-			auto pool = new LL::ThreadPool("General", poolSize, 1024*1024);
-			pool->start();
-			// Once we start shutting down, destroy this ThreadPool.
-			LLAppViewer::instance()->onCleanup([pool](){ delete pool; });
-		}
+        LLAppViewer::instance()->initGeneralThread();
 
 		// Initialize global class data needed for surfaces (i.e. textures)
 		LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;