SL-16421: Destroy the "General" ThreadPool as soon as cleanup starts.

Introduce LLAppViewer::onCleanup(), a method that accepts a nullary callable
to execute once viewer shutdown begins. Fire the collected callables in
LLAppViewer::cleanup().

In llstartup.cpp, instead of declaring a static unique_ptr and relying on
static object destruction to clean up the "General" ThreadPool, bind the
pointer to the new ThreadPool into an onCleanup() lambda that will delete it
when called. ~ThreadPool() takes care of orderly shutdown.
master
Nat Goodspeed 2021-11-30 15:22:26 -05:00
parent 9be88050e6
commit 01317a2fad
3 changed files with 31 additions and 11 deletions

View File

@ -1729,6 +1729,11 @@ void LLAppViewer::flushVFSIO()
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

View File

@ -49,6 +49,8 @@
#include "lltimer.h"
#include "llappcorehttp.h"
#include <boost/signals2.hpp>
class LLCommandLineParser;
class LLFrameTimer;
class LLPumpIO;
@ -189,10 +191,20 @@ public:
// On LoginCompleted callback
typedef boost::signals2::signal<void (void)> login_completed_signal_t;
login_completed_signal_t mOnLoginCompleted;
boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); }
boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb )
{
return mOnLoginCompleted.connect(cb);
}
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 purgeUserDataOnExit() { mPurgeUserDataOnExit = true; }
void purgeCache(); // Clear the local cache.
void purgeCacheImmediate(); //clear local cache immediately.

View File

@ -259,7 +259,6 @@ const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds
std::unique_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
std::unique_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
std::unique_ptr<LLViewerStats::PhaseMap> LLStartUp::sPhases(new LLViewerStats::PhaseMap);
std::unique_ptr<LL::ThreadPool> gGeneralThreadPool;
//
// local function declaration
@ -1495,15 +1494,19 @@ 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.
gGeneralThreadPool.reset(new LL::ThreadPool("General", poolSize, 1024*1024));
gGeneralThreadPool->start();
{
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; });
}
// Initialize global class data needed for surfaces (i.e. textures)
LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;