[Lldb-commits] [lldb] [lldb][progress][NFC] Add groundwork to keep track of progress reports (PR #81026)

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 7 13:39:23 PST 2024


================
@@ -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


More information about the lldb-commits mailing list