From 316bc0bdf30514a0c6894ef7c2859e79bf02a546 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 29 May 2024 09:49:56 -0400 Subject: Make ~ThreadPool() join every thread before destroying its vector. Otherwise we fall into the trap of destroying a joinable std::thread, which calls std::terminate() and hence our crash-on-terminate() handler. The previous ~ThreadPool() logic only joined threads if the queue wasn't already closed, but evidently we can reach the destructor with the queue closed but the threads not yet joined. Fixes #1534. --- indra/llcommon/threadpool.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index edccdb097b..0f445b84fb 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -109,20 +109,19 @@ LL::ThreadPoolBase::~ThreadPoolBase() void LL::ThreadPoolBase::close() { - if (! mQueue->isClosed()) + // mQueue might have been closed already, but in any case we must join or + // detach each of our threads before destroying the mThreads vector. + LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL; + mQueue->close(); + for (auto& pair: mThreads) { - LL_DEBUGS("ThreadPool") << mName << " closing queue and joining threads" << LL_ENDL; - mQueue->close(); - for (auto& pair: mThreads) + if (pair.second.joinable()) { - if (pair.second.joinable()) - { - LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; - pair.second.join(); - } + LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL; + pair.second.join(); } - LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL; } + LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL; } void LL::ThreadPoolBase::run(const std::string& name) -- cgit v1.2.3