diff options
| author | Mike <contact@mikelittman.me> | 2026-10-22 11:36:21 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-22 23:36:21 +0800 |
| commit | f2a1ad0e53632ad69729c9bd55edcdfe8ef98368 (patch) | |
| tree | 3c323a88a92d145dab4bd11f5e432bcefe0a796e | |
| parent | b087c0c8d818bace45a9d0d2dec3661f1261896d (diff) | |
Do not abort when a shutdown thread joins itself (#37)
std::thread::join throws system_error if the caller is the thread being
joined. That uncaught exception aborted the process during shutdown.
Detach the current thread instead, and catch a join that still throws.
| -rw-r--r-- | indra/llcommon/llthread.h | 26 | ||||
| -rw-r--r-- | indra/llcommon/threadpool.cpp | 12 | ||||
| -rw-r--r-- | indra/llcorehttp/llwebsocketmgr.cpp | 3 | ||||
| -rw-r--r-- | indra/llwebrtc/llwebrtc.cpp | 23 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 3 |
5 files changed, 63 insertions, 4 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; diff --git a/indra/llcorehttp/llwebsocketmgr.cpp b/indra/llcorehttp/llwebsocketmgr.cpp index ef07295eed..701fbd5446 100644 --- a/indra/llcorehttp/llwebsocketmgr.cpp +++ b/indra/llcorehttp/llwebsocketmgr.cpp @@ -28,6 +28,7 @@ #include "llwebsocketmgr.h" #include "llerror.h" +#include "llthread.h" #include "llsdserialize.h" #include "llhost.h" #include "llsdjson.h" @@ -508,7 +509,7 @@ void LLWebsocketMgr::WSServer::stop() << "thread-boundary regression." << LL_ENDL; } - mServerThread.join(); + ll_join_thread(mServerThread); LL_INFOS("WebSocket") << "WebSocket server thread joined for: " << mServerName << LL_ENDL; } onStopped(); diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d07f801051..ff68437cf3 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -29,6 +29,7 @@ #include <chrono> #include <future> #include <thread> +#include <system_error> #include <string.h> #include "api/audio/create_audio_device_module.h" #include "api/audio_codecs/audio_decoder_factory.h" @@ -558,7 +559,27 @@ bool LLWebRTCImpl::terminate() return false; } - shutdown_thread.join(); + // Joining the current thread throws system_error and aborts the process. + if (shutdown_thread.get_id() == std::this_thread::get_id()) + { + RTC_LOG(LS_WARNING) << __FUNCTION__ << ": shutdown thread is the caller; detaching."; + shutdown_thread.detach(); + } + else + { + try + { + shutdown_thread.join(); + } + catch (const std::system_error& e) + { + RTC_LOG(LS_WARNING) << __FUNCTION__ << ": join failed: " << e.what(); + if (shutdown_thread.joinable()) + { + shutdown_thread.detach(); + } + } + } webrtc::LogMessage::RemoveLogToStream(mLogSink); return true; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b818a66b30..31fd699335 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -31,6 +31,7 @@ #include <thread> #include "llinventorymodel.h" +#include "llthread.h" #include "llaisapi.h" #include "llagent.h" @@ -2505,7 +2506,7 @@ void LLInventoryModel::waitForPendingCacheWrites() { if (thread.joinable()) { - thread.join(); + ll_join_thread(thread); } } sPendingCacheThreads.clear(); |
