Skip to content

Commit 51e9f66

Browse files
author
George Hu
committed
[lldb] Fix deadlock in parallel module loading with separate symbol thread pool
1 parent 4f33d7b commit 51e9f66

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,11 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
506506
/// Shared thread pool. Use only with ThreadPoolTaskGroup.
507507
static llvm::ThreadPoolInterface &GetThreadPool();
508508

509+
/// Dedicated symbol thread pool to prevent deadlock with module loading.
510+
/// Use this for symbol indexing operations that might need to access
511+
/// the shared module list while holding module mutexes.
512+
static llvm::ThreadPoolInterface &GetSymbolThreadPool();
513+
509514
/// Report warning events.
510515
///
511516
/// Warning events will be delivered to any debuggers that have listeners

lldb/source/Core/Debugger.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static std::recursive_mutex *g_debugger_list_mutex_ptr =
110110
static Debugger::DebuggerList *g_debugger_list_ptr =
111111
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
112112
static llvm::DefaultThreadPool *g_thread_pool = nullptr;
113+
static llvm::DefaultThreadPool *g_symbol_thread_pool = nullptr;
113114

114115
static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
115116
{
@@ -715,6 +716,8 @@ void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
715716
g_debugger_list_mutex_ptr = new std::recursive_mutex();
716717
g_debugger_list_ptr = new DebuggerList();
717718
g_thread_pool = new llvm::DefaultThreadPool(llvm::optimal_concurrency());
719+
g_symbol_thread_pool =
720+
new llvm::DefaultThreadPool(llvm::optimal_concurrency());
718721
g_load_plugin_callback = load_plugin_callback;
719722
}
720723

@@ -731,6 +734,13 @@ void Debugger::Terminate() {
731734
if (g_thread_pool) {
732735
// The destructor will wait for all the threads to complete.
733736
delete g_thread_pool;
737+
g_thread_pool = nullptr;
738+
}
739+
740+
if (g_symbol_thread_pool) {
741+
// The destructor will wait for all the threads to complete.
742+
delete g_symbol_thread_pool;
743+
g_symbol_thread_pool = nullptr;
734744
}
735745

736746
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
@@ -2383,3 +2393,9 @@ llvm::ThreadPoolInterface &Debugger::GetThreadPool() {
23832393
"Debugger::GetThreadPool called before Debugger::Initialize");
23842394
return *g_thread_pool;
23852395
}
2396+
2397+
llvm::ThreadPoolInterface &Debugger::GetSymbolThreadPool() {
2398+
assert(g_symbol_thread_pool &&
2399+
"Debugger::GetSymbolThreadPool called before Debugger::Initialize");
2400+
return *g_symbol_thread_pool;
2401+
}

lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ void ManualDWARFIndex::Index() {
8686
total_progress, /*debugger=*/nullptr,
8787
Progress::kDefaultHighFrequencyReportTime);
8888

89+
// Use separate symbol thread pool to avoid deadlock with module loading
8990
// Share one thread pool across operations to avoid the overhead of
9091
// recreating the threads.
91-
llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
92-
const size_t num_threads = Debugger::GetThreadPool().getMaxConcurrency();
92+
llvm::ThreadPoolTaskGroup task_group(Debugger::GetSymbolThreadPool());
93+
const size_t num_threads =
94+
Debugger::GetSymbolThreadPool().getMaxConcurrency();
9395

9496
// Run a function for each compile unit in parallel using as many threads as
9597
// are available. This is significantly faster than submiting a new task for

0 commit comments

Comments
 (0)