[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