================ @@ -9,26 +9,34 @@ #include "lldb/Core/Progress.h" #include "lldb/Core/Debugger.h" -#include "lldb/Utility/StreamString.h" #include <optional> using namespace lldb; using namespace lldb_private; std::atomic<uint64_t> Progress::g_id(0); +std::atomic<uint64_t> Progress::g_refcount(1); +std::unordered_map<std::string, uint64_t> Progress::g_map = {}; ---------------- clayborg wrote:
When something isn't just an integer, like the map here, we can run into issues with this in a multi-threaded environment. Why? These variables are part of the global C++ constructor / destructor chain. If any thread uses these after the main thread shuts down it can cause a crash. So for global objects we typically will create a pointer to one and leak it with a note. See `lldb/source/Core/Debugger.cpp` and look for `g_debugger_list_mutex_ptr` and other variables right next to them and then see `Debugger::Initialize()`. This map also need to be threadsafe, so it needs a mutex. Might be a good idea to create a class to contain these and use an accessor to provide access to it. The solution below will make something that is thread safe _and_ also something that will survive the global destructor chain being called and letting other threads still be able to use Progress objects without crashing the process: ``` namespace { class ProgressCategoryMap { std::mutex m_mutex; std::unordered_map<std::string, uint64_t> m_map; void Increment(std::string title) { std::lock_guard<std::mutex> lock(m_mutex); auto pair = g_map.emplace(title, 1); // No need to use g_refcount as it is just a constant 1 // pair.first will be true if insertion happened. if (pair.first == false) ++pair.second; // Key already in map, increment the ref count. } void Decrement(std::string title) { std::lock_guard<std::mutex> lock(m_mutex); auto pos = g_map.find(title); if (pos == g_map.end()) return; if (--pos->second == 0) g_map.erase(pos->second); // Decremented to zero } }; // Now make a global accessor to get a threadsafe copy of ProgressCategoryMap ProgressCategoryMap *GetProgressCategoryMap() { static std::once_flag g_once; static ProgressCategoryMap *g_category_map_ptr = nullptr; std::call_once(g_once, []{ // NOTE: intentional leak to avoid issues with C++ destructor chain g_category_map_ptr = new ProgressCategoryMap(); }); return g_category_map_ptr; } } // anonymous namespace ``` https://github.com/llvm/llvm-project/pull/81026 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits