[Lldb-commits] [lldb] [lldb] Guard CompileUnit's lazily parsed data with the Module's lock (PR #223662)
Raphael Isemann via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 15 04:33:04 PDT 2026
https://github.com/Teemperor created https://github.com/llvm/llvm-project/pull/223662
CompileUnit has several lazy members that can be accessed by several threads but that don't synchronize their lazy-loading mechanism. This causes that some threads see the in-flight values when they access these values.
This patch synchronizes all lazy-loading using the module's mutex.
This is a prerequisite for PR #220395 that adds a basic multithreaded test and which would otherwise randomly fail.
>From 99d61fa9359c9aceb7cb60373aa60b351a1dc509 Mon Sep 17 00:00:00 2001
From: Raphael Isemann <rise at apple.com>
Date: Fri, 14 Aug 2026 11:17:42 +0100
Subject: [PATCH] [lldb] Guard CompileUnit's lazily parsed data with the
Module's lock
CompileUnit has several lazy members that can be accessed by several
threads but that don't synchronize their lazy-loading mechanism. This
causes that some threads see the in-flight values when they access
these values.
This patch synchronizes all lazy-loading using the module's mutex.
This is a prerequisite for PR #220395 that adds a basic multithreaded
test and which would otherwise randomly fail.
---
lldb/include/lldb/Symbol/CompileUnit.h | 2 ++
lldb/source/Core/ModuleChild.cpp | 1 +
lldb/source/Symbol/CompileUnit.cpp | 40 ++++++++++++++++++++++----
3 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index bb9594699df33..02ac2416adf7b 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -460,6 +460,8 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
(1u << 6) ///< Have we parsed the debug macros already?
};
+ std::recursive_mutex &GetMutex() const;
+
CompileUnit(const CompileUnit &) = delete;
const CompileUnit &operator=(const CompileUnit &) = delete;
const char *GetCachedLanguage() const;
diff --git a/lldb/source/Core/ModuleChild.cpp b/lldb/source/Core/ModuleChild.cpp
index 7aaa8f2ac2508..9df17ff6b4988 100644
--- a/lldb/source/Core/ModuleChild.cpp
+++ b/lldb/source/Core/ModuleChild.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ModuleChild.h"
+#include <cassert>
using namespace lldb_private;
diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp
index 703ef131ad6bf..8de077d5a24b4 100644
--- a/lldb/source/Symbol/CompileUnit.cpp
+++ b/lldb/source/Symbol/CompileUnit.cpp
@@ -153,10 +153,13 @@ FunctionSP CompileUnit::FindFunctionByUID(lldb::user_id_t func_uid) {
}
lldb::LanguageType CompileUnit::GetLanguage() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_language == eLanguageTypeUnknown) {
if (m_flags.IsClear(flagsParsedLanguage)) {
m_flags.Set(flagsParsedLanguage);
- if (SymbolFile *symfile = GetModule()->GetSymbolFile())
+ if (SymbolFile *symfile = module_sp->GetSymbolFile())
m_language = symfile->ParseLanguage(*this);
}
}
@@ -164,10 +167,15 @@ lldb::LanguageType CompileUnit::GetLanguage() {
}
LineTable *CompileUnit::GetLineTable() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_line_table_up == nullptr) {
+ // The flag is set before parsing so that a SymbolFile that asks for the
+ // line table while parsing it doesn't recurse forever.
if (m_flags.IsClear(flagsParsedLineTable)) {
m_flags.Set(flagsParsedLineTable);
- if (SymbolFile *symfile = GetModule()->GetSymbolFile())
+ if (SymbolFile *symfile = module_sp->GetSymbolFile())
symfile->ParseLineTable(*this);
}
}
@@ -175,6 +183,8 @@ LineTable *CompileUnit::GetLineTable() {
}
void CompileUnit::SetLineTable(LineTable *line_table) {
+ // SymbolFile calls this while holding the Module's lock, which is the lock
+ // GetLineTable() takes as well.
if (line_table == nullptr)
m_flags.Clear(flagsParsedLineTable);
else
@@ -183,10 +193,13 @@ void CompileUnit::SetLineTable(LineTable *line_table) {
}
DebugMacros *CompileUnit::GetDebugMacros() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_debug_macros_sp.get() == nullptr) {
if (m_flags.IsClear(flagsParsedDebugMacros)) {
m_flags.Set(flagsParsedDebugMacros);
- if (SymbolFile *symfile = GetModule()->GetSymbolFile())
+ if (SymbolFile *symfile = module_sp->GetSymbolFile())
symfile->ParseDebugMacros(*this);
}
}
@@ -490,9 +503,12 @@ void CompileUnit::ResolveSymbolContext(
}
bool CompileUnit::GetIsOptimized() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_is_optimized == eLazyBoolCalculate) {
m_is_optimized = eLazyBoolNo;
- if (SymbolFile *symfile = GetModule()->GetSymbolFile()) {
+ if (SymbolFile *symfile = module_sp->GetSymbolFile()) {
if (symfile->ParseIsOptimized(*this))
m_is_optimized = eLazyBoolYes;
}
@@ -500,15 +516,24 @@ bool CompileUnit::GetIsOptimized() {
return m_is_optimized;
}
+std::recursive_mutex &CompileUnit::GetMutex() const {
+ ModuleSP module_sp = GetModule();
+ assert(module_sp && "Called without module?");
+ return module_sp->GetMutex();
+}
+
void CompileUnit::SetVariableList(VariableListSP &variables) {
m_variables = variables;
}
const std::vector<SourceModule> &CompileUnit::GetImportedModules() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_imported_modules.empty() &&
m_flags.IsClear(flagsParsedImportedModules)) {
m_flags.Set(flagsParsedImportedModules);
- if (SymbolFile *symfile = GetModule()->GetSymbolFile()) {
+ if (SymbolFile *symfile = module_sp->GetSymbolFile()) {
SymbolContext sc;
CalculateSymbolContext(&sc);
symfile->ParseImportedModules(sc, m_imported_modules);
@@ -526,10 +551,13 @@ bool CompileUnit::ForEachExternalModule(
}
const SupportFileList &CompileUnit::GetSupportFiles() {
+ ModuleSP module_sp = GetModule();
+
+ std::lock_guard<std::recursive_mutex> guard(GetMutex());
if (m_support_files.GetSize() == 0) {
if (m_flags.IsClear(flagsParsedSupportFiles)) {
m_flags.Set(flagsParsedSupportFiles);
- if (SymbolFile *symfile = GetModule()->GetSymbolFile())
+ if (SymbolFile *symfile = module_sp->GetSymbolFile())
symfile->ParseSupportFiles(*this, m_support_files);
}
}
More information about the lldb-commits
mailing list