jgorbe created this revision.
jgorbe added reviewers: labath, JDevlieghere.
Herald added a subscriber: pengfei.
Herald added a project: All.
jgorbe requested review of this revision.
Herald added a project: LLDB.

I've noticed (what looked like) deadlocking behavior while running some
Python code that registers categories and formatters from a separate
thread. I ran lldb and my scripts through Helgrind and got (among other
unrelated reports) the report below.

In summary, there are two mutexes (`TypeCategoryMap::m_map_mutex` and
`FormatManager::m_language_categories_mutex`) that sometimes get
acquired in different order. This change attempts to fix that by
reducing the scope of the locks that appear in the Helgrind report.

- `TypeCategoryMap::Add` locks `m_map_mutex` and keeps holding it while 
notifying `listener`. The listener class shouldn't touch any data in 
`TypeCategoryMap` (because everything is private), except by using the class' 
own methods, and all of them acquire the mutex on entry.

  This change makes it release the lock after `m_map_mutex` is updated, but 
before the listener is invoked.

- `FormatManager::GetCategoryForLanguage` does a map lookup (holding 
`m_language_categories_mutex`) and, if the lookup fails, constructs a new 
`LanguageCategory`. This also results in listeners being called while still 
holding the mutex.

  This patch changes it so that the lock is only held during initial lookup. If 
lookup fails, the new category will be created and only then we'll acquire the 
lock again to insert the new category into the map.

Here's the Helgrind report for reference:

  ==3574084== ----------------------------------------------------------------
  ==3574084==
  ==3574084== Thread #6: lock order "0x1472C070 before 0x1472C110" violated
  ==3574084==
  ==3574084== Observed (incorrect) order is: acquisition of lock at 0x1472C110
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2F1E04: 
lldb_private::TypeCategoryMap::Add(lldb_private::ConstString, 
std::shared_ptr<lldb_private::TypeCategoryImpl> const&) 
(llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:28)
  ==3574084==    by 0xB2D8A57: 
lldb_private::FormatManager::GetCategory(lldb_private::ConstString, bool) 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:423)
  ==3574084==    by 0xB2D380B: 
lldb_private::DataVisualization::Categories::GetCategory(lldb_private::ConstString,
 std::shared_ptr<lldb_private::TypeCategoryImpl>&, bool) 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:79)
  ==3574084==    by 0xAE47DFD: lldb::SBDebugger::CreateCategory(char const*) 
(llvm/lldb/source/API/SBDebugger.cpp:1535)
  ==3574084==    by 0xAF7BA0B: _wrap_SBDebugger_CreateCategory(_object*, 
_object*) (LLDBWrapPython.cpp:24738)
  ==3574084==    by 0x14E77483: ??? (in 
/usr/lib/x86_64-linux-gnu/libpython3.9.so.1.0)
  ==3574084==    by 0x14E33A07: _PyObject_MakeTpCall (in 
/usr/lib/x86_64-linux-gnu/libpython3.9.so.1.0)
  ==3574084==
  ==3574084==  followed by a later acquisition of lock at 0x1472C070
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2D6DDA: lldb_private::FormatManager::Changed() 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:118)
  ==3574084==    by 0xB2F1E46: 
lldb_private::TypeCategoryMap::Add(lldb_private::ConstString, 
std::shared_ptr<lldb_private::TypeCategoryImpl> const&) 
(llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:31)
  ==3574084==    by 0xB2D8A57: 
lldb_private::FormatManager::GetCategory(lldb_private::ConstString, bool) 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:423)
  ==3574084==    by 0xB2D380B: 
lldb_private::DataVisualization::Categories::GetCategory(lldb_private::ConstString,
 std::shared_ptr<lldb_private::TypeCategoryImpl>&, bool) 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:79)
  ==3574084==    by 0xAE47DFD: lldb::SBDebugger::CreateCategory(char const*) 
(llvm/lldb/source/API/SBDebugger.cpp:1535)
  ==3574084==    by 0xAF7BA0B: _wrap_SBDebugger_CreateCategory(_object*, 
_object*) (LLDBWrapPython.cpp:24738)
  ==3574084==    by 0x14E77483: ??? (in 
/usr/lib/x86_64-linux-gnu/libpython3.9.so.1.0)
  ==3574084==
  ==3574084== Required order was established by acquisition of lock at 
0x1472C070
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2D92A3: 
lldb_private::FormatManager::GetCategoryForLanguage(lldb::LanguageType) 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:586)
  ==3574084==    by 0xB2DAB24: std::shared_ptr<lldb_private::TypeFormatImpl> 
lldb_private::FormatManager::Get<std::shared_ptr<lldb_private::TypeFormatImpl> 
>(lldb_private::ValueObject&, lldb::DynamicValueType) 
(llvm/lldb/source/DataFormatters/Form
  atManager.cpp:620)
  ==3574084==    by 0xB2D93C0: 
lldb_private::FormatManager::GetFormat(lldb_private::ValueObject&, 
lldb::DynamicValueType) (llvm/lldb/source/DataFormatters/FormatManager.cpp:671)
  ==3574084==    by 0xB2D3565: 
lldb_private::DataVisualization::GetFormat(lldb_private::ValueObject&, 
lldb::DynamicValueType) 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:33)
  ==3574084==    by 0xB2AC762: 
lldb_private::ValueObject::UpdateFormatsIfNeeded() 
(llvm/lldb/source/Core/ValueObject.cpp:217)
  ==3574084==    by 0xB2AC245: 
lldb_private::ValueObject::UpdateValueIfNeeded(bool) 
(llvm/lldb/source/Core/ValueObject.cpp:116)
  ==3574084==    by 0xB2FD1B2: 
lldb_private::ValueObjectPrinter::GetMostSpecializedValue() 
(llvm/lldb/source/DataFormatters/ValueObjectPrinter.cpp:101)
  ==3574084==
  ==3574084==  followed by a later acquisition of lock at 0x1472C110
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2F20C4: 
lldb_private::TypeCategoryMap::Get(lldb_private::ConstString, 
std::shared_ptr<lldb_private::TypeCategoryImpl>&) 
(llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:134)
  ==3574084==    by 0xB2D89A6: 
lldb_private::FormatManager::GetCategory(lldb_private::ConstString, bool) 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:417)
  ==3574084==    by 0xB2D380B: 
lldb_private::DataVisualization::Categories::GetCategory(lldb_private::ConstString,
 std::shared_ptr<lldb_private::TypeCategoryImpl>&, bool) 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:79)
  ==3574084==    by 0xB75D5B2: 
lldb_private::CPlusPlusLanguage::GetFormatters()::$_0::operator()() const 
(llvm/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp:1246)
  ==3574084==    by 0xB75D55C: void std::__invoke_impl<void, 
lldb_private::CPlusPlusLanguage::GetFormatters()::$_0>(std::__invoke_other, 
lldb_private::CPlusPlusLanguage::GetFormatters()::$_0&&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../inclu
  de/c++/11/bits/invoke.h:61)
  ==3574084==    by 0xB75D52C: 
std::__invoke_result<lldb_private::CPlusPlusLanguage::GetFormatters()::$_0>::type
 
std::__invoke<lldb_private::CPlusPlusLanguage::GetFormatters()::$_0>(lldb_private::CPlusPlusLanguage::GetFormatters()::$_0&&)
 (bin/../
  lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96)
  ==3574084==    by 0xB75D4FF: 
std::call_once<lldb_private::CPlusPlusLanguage::GetFormatters()::$_0>(std::once_flag&,
 
lldb_private::CPlusPlusLanguage::GetFormatters()::$_0&&)::{lambda()#1}::operator()()
 const (bin/../lib/gcc/x86_64-linux-gnu/11/..
  /../../../include/c++/11/mutex:776)
  ==3574084==
  ==3574084==  Lock at 0x1472C070 was first observed
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2D6DDA: lldb_private::FormatManager::Changed() 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:118)
  ==3574084==    by 0xB2F1E46: 
lldb_private::TypeCategoryMap::Add(lldb_private::ConstString, 
std::shared_ptr<lldb_private::TypeCategoryImpl> const&) 
(llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:31)
  ==3574084==    by 0xB2F1DB6: 
lldb_private::TypeCategoryMap::TypeCategoryMap(lldb_private::IFormatChangeListener*)
 (llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:23)
  ==3574084==    by 0xB2D9511: lldb_private::FormatManager::FormatManager() 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:689)
  ==3574084==    by 0xB2D34A1: GetFormatManager() 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:16)
  ==3574084==    by 0xB2D3458: lldb_private::DataVisualization::ForceUpdate() 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:20)
  ==3574084==    by 0xE514F28: 
lldb_private::CommandObjectScript::DoExecute(llvm::StringRef, 
lldb_private::CommandReturnObject&) 
(llvm/lldb/source/Commands/CommandObjectScript.cpp:121)
  ==3574084==  Address 0x1472c070 is 120 bytes inside data symbol 
"_ZZL16GetFormatManagervE16g_format_manager"
  ==3574084==
  ==3574084==  Lock at 0x1472C110 was first observed
  ==3574084==  Lock at 0x1472C110 was first observed
  ==3574084==    at 0x484777F: mutex_lock_WRK (hg_intercepts.c:942)
  ==3574084==    by 0xADFF5E2: __gthread_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:749)
  ==3574084==    by 0xADFF5B4: __gthread_recursive_mutex_lock(pthread_mutex_t*) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:811)
  ==3574084==    by 0xAE00D34: std::recursive_mutex::lock() 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:108)
  ==3574084==    by 0xADFFEB2: 
std::lock_guard<std::recursive_mutex>::lock_guard(std::recursive_mutex&) 
(bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_mutex.h:229)
  ==3574084==    by 0xB2F1E04: 
lldb_private::TypeCategoryMap::Add(lldb_private::ConstString, 
std::shared_ptr<lldb_private::TypeCategoryImpl> const&) 
(llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:28)
  ==3574084==    by 0xB2F1DB6: 
lldb_private::TypeCategoryMap::TypeCategoryMap(lldb_private::IFormatChangeListener*)
 (llvm/lldb/source/DataFormatters/TypeCategoryMap.cpp:23)
  ==3574084==    by 0xB2D9511: lldb_private::FormatManager::FormatManager() 
(llvm/lldb/source/DataFormatters/FormatManager.cpp:689)
  ==3574084==    by 0xB2D34A1: GetFormatManager() 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:16)
  ==3574084==    by 0xB2D3458: lldb_private::DataVisualization::ForceUpdate() 
(llvm/lldb/source/DataFormatters/DataVisualization.cpp:20)
  ==3574084==    by 0xE514F28: 
lldb_private::CommandObjectScript::DoExecute(llvm::StringRef, 
lldb_private::CommandReturnObject&) 
(llvm/lldb/source/Commands/CommandObjectScript.cpp:121)
  ==3574084==    by 0xB3AF4B3: lldb_private::CommandObjectRaw::Execute(char 
const*, lldb_private::CommandReturnObject&) 
(llvm/lldb/source/Interpreter/CommandObject.cpp:1020)
  ==3574084==  Address 0x1472c110 is 280 bytes inside data symbol 
"_ZZL16GetFormatManagervE16g_format_manager"
  ==3574084==
  ==3574084==
  ==3574084== ----------------------------------------------------------------


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D126240

Files:
  lldb/source/DataFormatters/FormatManager.cpp
  lldb/source/DataFormatters/TypeCategoryMap.cpp


Index: lldb/source/DataFormatters/TypeCategoryMap.cpp
===================================================================
--- lldb/source/DataFormatters/TypeCategoryMap.cpp
+++ lldb/source/DataFormatters/TypeCategoryMap.cpp
@@ -25,8 +25,10 @@
 }
 
 void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) {
-  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
-  m_map[name] = entry;
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
+    m_map[name] = entry;
+  }
   if (listener)
     listener->Changed();
 }
Index: lldb/source/DataFormatters/FormatManager.cpp
===================================================================
--- lldb/source/DataFormatters/FormatManager.cpp
+++ lldb/source/DataFormatters/FormatManager.cpp
@@ -583,14 +583,19 @@
 
 LanguageCategory *
 FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
-  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
-  auto iter = m_language_categories_map.find(lang_type),
-       end = m_language_categories_map.end();
-  if (iter != end)
-    return iter->second.get();
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
+    auto iter = m_language_categories_map.find(lang_type),
+         end = m_language_categories_map.end();
+    if (iter != end)
+      return iter->second.get();
+  }
   LanguageCategory *lang_category = new LanguageCategory(lang_type);
-  m_language_categories_map[lang_type] =
-      LanguageCategory::UniquePointer(lang_category);
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
+    m_language_categories_map[lang_type] =
+        LanguageCategory::UniquePointer(lang_category);
+  }
   return lang_category;
 }
 


Index: lldb/source/DataFormatters/TypeCategoryMap.cpp
===================================================================
--- lldb/source/DataFormatters/TypeCategoryMap.cpp
+++ lldb/source/DataFormatters/TypeCategoryMap.cpp
@@ -25,8 +25,10 @@
 }
 
 void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) {
-  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
-  m_map[name] = entry;
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
+    m_map[name] = entry;
+  }
   if (listener)
     listener->Changed();
 }
Index: lldb/source/DataFormatters/FormatManager.cpp
===================================================================
--- lldb/source/DataFormatters/FormatManager.cpp
+++ lldb/source/DataFormatters/FormatManager.cpp
@@ -583,14 +583,19 @@
 
 LanguageCategory *
 FormatManager::GetCategoryForLanguage(lldb::LanguageType lang_type) {
-  std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
-  auto iter = m_language_categories_map.find(lang_type),
-       end = m_language_categories_map.end();
-  if (iter != end)
-    return iter->second.get();
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
+    auto iter = m_language_categories_map.find(lang_type),
+         end = m_language_categories_map.end();
+    if (iter != end)
+      return iter->second.get();
+  }
   LanguageCategory *lang_category = new LanguageCategory(lang_type);
-  m_language_categories_map[lang_type] =
-      LanguageCategory::UniquePointer(lang_category);
+  {
+    std::lock_guard<std::recursive_mutex> guard(m_language_categories_mutex);
+    m_language_categories_map[lang_type] =
+        LanguageCategory::UniquePointer(lang_category);
+  }
   return lang_category;
 }
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to