Index: lldb/source/Core/Debugger.cpp =================================================================== --- lldb/source/Core/Debugger.cpp +++ lldb/source/Core/Debugger.cpp @@ -104,6 +104,7 @@ nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain static DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain +static llvm::ThreadPool *g_thread_pool = nullptr; static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { { @@ -539,12 +540,18 @@ g_debugger_list_mutex_ptr = new std::recursive_mutex(); g_debugger_list_ptr = new DebuggerList(); g_load_plugin_callback = load_plugin_callback; + g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency()); } void Debugger::Terminate() { assert(g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"); + if (g_thread_pool) { + // The destructor will wait for all the threads to complete. + delete g_thread_pool; + } + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { // Clear our global list of debugger objects { @@ -2005,11 +2012,7 @@ } llvm::ThreadPool &Debugger::GetThreadPool() { - // NOTE: intentional leak to avoid issues with C++ destructor chain - static llvm::ThreadPool *g_thread_pool = nullptr; - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency()); - }); + assert(g_thread_pool && + "Debugger::GetThreadPool called before Debugger::Initialize"); return *g_thread_pool; }