Skip to content

Commit

Permalink
[lldb] Tighten lock in Language::ForEach
Browse files Browse the repository at this point in the history
It is easy to accidentally introduce a deadlock by having the callback
passed to Language::ForEach also attempt to acquire the same lock. It
is easy enough to disallow the callback from calling anything in
Language directly, but it may happen through a series of other
function/method calls.

The solution I am proposing is to tighten the lock in Language::ForEach
so that it is only held as we gather the currently loaded language
plugins. We store them in a vector and then iterate through them with
the callback so that the callback can't introduce a deadlock.

Differential Revision: https://reviews.llvm.org/D109013
  • Loading branch information
bulbazord committed Aug 31, 2021
1 parent b04b757 commit 862a311
Showing 1 changed file with 15 additions and 4 deletions.
19 changes: 15 additions & 4 deletions lldb/source/Target/Language.cpp
Expand Up @@ -108,10 +108,21 @@ void Language::ForEach(std::function<bool(Language *)> callback) {
}
});

std::lock_guard<std::mutex> guard(GetLanguagesMutex());
LanguagesMap &map(GetLanguagesMap());
for (const auto &entry : map) {
if (!callback(entry.second.get()))
// callback may call a method in Language that attempts to acquire the same
// lock (such as Language::ForEach or Language::FindPlugin). To avoid a
// deadlock, we do not use callback while holding the lock.
std::vector<Language *> loaded_plugins;
{
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
LanguagesMap &map(GetLanguagesMap());
for (const auto &entry : map) {
if (entry.second)
loaded_plugins.push_back(entry.second.get());
}
}

for (auto *lang : loaded_plugins) {
if (!callback(lang))
break;
}
}
Expand Down

0 comments on commit 862a311

Please sign in to comment.