Skip to content

Commit 5752e31

Browse files
v-bulleVincent Belliard
andauthored
[lldb] fix dead lock in TypeCategoryMap.cpp (llvm#87540)
FormatManager::GetCategoryForLanguage and FormatManager::GetCategory(can_create = true) can be called concurrently and they both take the TypeCategory::m_map_mutex and the FormatManager::m_language_categories_mutex but in reverse order. On one thread, GetCategoryForLanguage takes m_language_categories_mutex and then ends calling TypeCategoryMap::Get which takes m_map_mutex On another thread GetCategory calls TypeCategoryMap::Add which takes m_map_mutex and then calls FormatManager::Changed() which takes m_language_categories_mutex If both threads are running concurrently, we have a dead lock. The patch releases the m_map_mutex before calling Changed which avoids the dead lock. --------- Co-authored-by: Vincent Belliard <[email protected]>
1 parent a27ab3f commit 5752e31

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

lldb/source/DataFormatters/TypeCategoryMap.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,31 @@ TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
2525
}
2626

2727
void TypeCategoryMap::Add(KeyType name, const TypeCategoryImplSP &entry) {
28-
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
29-
m_map[name] = entry;
28+
{
29+
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
30+
m_map[name] = entry;
31+
}
32+
// Release the mutex to avoid a potential deadlock between
33+
// TypeCategoryMap::m_map_mutex and
34+
// FormatManager::m_language_categories_mutex which can be acquired in
35+
// reverse order when calling FormatManager::Changed.
3036
if (listener)
3137
listener->Changed();
3238
}
3339

3440
bool TypeCategoryMap::Delete(KeyType name) {
35-
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
36-
MapIterator iter = m_map.find(name);
37-
if (iter == m_map.end())
38-
return false;
39-
m_map.erase(name);
40-
Disable(name);
41+
{
42+
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
43+
MapIterator iter = m_map.find(name);
44+
if (iter == m_map.end())
45+
return false;
46+
m_map.erase(name);
47+
Disable(name);
48+
}
49+
// Release the mutex to avoid a potential deadlock between
50+
// TypeCategoryMap::m_map_mutex and
51+
// FormatManager::m_language_categories_mutex which can be acquired in
52+
// reverse order when calling FormatManager::Changed.
4153
if (listener)
4254
listener->Changed();
4355
return true;
@@ -123,9 +135,15 @@ void TypeCategoryMap::DisableAllCategories() {
123135
}
124136

125137
void TypeCategoryMap::Clear() {
126-
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
127-
m_map.clear();
128-
m_active_categories.clear();
138+
{
139+
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
140+
m_map.clear();
141+
m_active_categories.clear();
142+
}
143+
// Release the mutex to avoid a potential deadlock between
144+
// TypeCategoryMap::m_map_mutex and
145+
// FormatManager::m_language_categories_mutex which can be acquired in
146+
// reverse order when calling FormatManager::Changed.
129147
if (listener)
130148
listener->Changed();
131149
}

0 commit comments

Comments
 (0)