summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llthread.h26
-rw-r--r--indra/llcommon/threadpool.cpp12
2 files changed, 37 insertions, 1 deletions
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index b97d479abc..38a5f4669f 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -33,6 +33,32 @@
extern void set_thread_name(const char* threadName);
+// Join unless this is the calling thread. Joining the current thread throws
+// system_error(resource_deadlock_would_occur) and aborts via std::terminate.
+inline void ll_join_thread(std::thread& thread)
+{
+ if (!thread.joinable())
+ {
+ return;
+ }
+ if (thread.get_id() == std::this_thread::get_id())
+ {
+ thread.detach();
+ return;
+ }
+ try
+ {
+ thread.join();
+ }
+ catch (const std::system_error&)
+ {
+ if (thread.joinable())
+ {
+ thread.detach();
+ }
+ }
+}
+
namespace LLTrace
{
class ThreadRecorder;
diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp
index 6adbdffba8..668c8ba598 100644
--- a/indra/llcommon/threadpool.cpp
+++ b/indra/llcommon/threadpool.cpp
@@ -20,6 +20,7 @@
#include "commoncontrol.h"
#include "llerror.h"
#include "llevents.h"
+#include "llthread.h"
#include "llsd.h"
#include "stringize.h"
@@ -127,8 +128,17 @@ void LL::ThreadPoolBase::close()
{
if (pair.second.joinable())
{
+ // close() runs on a worker when the LLApp status listener
+ // fires on that thread. Joining it throws and aborts shutdown.
+ if (pair.second.get_id() == std::this_thread::get_id())
+ {
+ LL_WARNS("ThreadPool") << mName << " detaching current thread "
+ << pair.first << LL_ENDL;
+ pair.second.detach();
+ continue;
+ }
LL_DEBUGS("ThreadPool") << mName << " waiting on thread " << pair.first << LL_ENDL;
- pair.second.join();
+ ll_join_thread(pair.second);
}
}
LL_DEBUGS("ThreadPool") << mName << " shutdown complete" << LL_ENDL;