Skip to content

Commit 5a04596

Browse files
committed
Use call_once in InstanceImpl(), leak progress manager object
In order to prevent potential crashes when LLDB is terminated, this commit instead creates the instance for the progress manager in a `call_once` within its initializer.
1 parent f5ef078 commit 5a04596

File tree

2 files changed

+16
-24
lines changed

2 files changed

+16
-24
lines changed

lldb/include/lldb/Core/Progress.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,15 @@ class ProgressManager {
129129
ProgressManager();
130130
~ProgressManager();
131131

132-
static void Initialize();
133-
static void Terminate();
134-
// Control the refcount of the progress report category as needed
132+
/// Control the refcount of the progress report category as needed.
135133
void Increment(std::string category);
136134
void Decrement(std::string category);
137135

138-
// Public accessor for the class instance
139136
static ProgressManager &Instance();
140137

141138
private:
142-
// Manage the class instance internally using a std::optional
143-
static std::optional<ProgressManager> &InstanceImpl();
139+
/// Manage the class instance internally.
140+
static ProgressManager &InstanceImpl();
144141

145142
llvm::StringMap<uint64_t> m_progress_category_map;
146143
std::mutex m_progress_map_mutex;

lldb/source/Core/Progress.cpp

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "lldb/Core/Debugger.h"
1212
#include "lldb/Utility/StreamString.h"
1313

14+
#include <mutex>
1415
#include <optional>
1516

1617
using namespace lldb;
@@ -67,34 +68,28 @@ void Progress::ReportProgress() {
6768
}
6869
}
6970

70-
void ProgressManager::Initialize() {
71-
lldbassert(!InstanceImpl() && "A progress report manager already exists.");
72-
InstanceImpl().emplace();
73-
}
74-
75-
void ProgressManager::Terminate() {
76-
lldbassert(InstanceImpl() &&
77-
"A progress report manager has already been terminated.");
78-
InstanceImpl().reset();
79-
}
80-
81-
std::optional<ProgressManager> &ProgressManager::InstanceImpl() {
82-
static std::optional<ProgressManager> g_progress_manager;
83-
return g_progress_manager;
71+
ProgressManager &ProgressManager::InstanceImpl() {
72+
static std::once_flag g_once_flag;
73+
static ProgressManager *g_progress_manager = nullptr;
74+
std::call_once(g_once_flag, []() {
75+
// NOTE: known leak to avoid global destructor chain issues.
76+
g_progress_manager = new ProgressManager();
77+
});
78+
return *g_progress_manager;
8479
}
8580

8681
ProgressManager::ProgressManager() : m_progress_category_map() {}
8782

8883
ProgressManager::~ProgressManager() {}
8984

90-
ProgressManager &ProgressManager::Instance() { return *InstanceImpl(); }
85+
ProgressManager &ProgressManager::Instance() { return InstanceImpl(); }
9186

9287
void ProgressManager::Increment(std::string title) {
9388
std::lock_guard<std::mutex> lock(m_progress_map_mutex);
9489
auto pair = m_progress_category_map.insert(std::pair(title, 1));
9590

9691
// If pair.first is not empty after insertion it means that that
97-
// category was entered for the first time and should not be incremented
92+
// category was entered for the first time and should not be incremented.
9893
if (!pair.second)
9994
++pair.first->second;
10095
}
@@ -103,10 +98,10 @@ void ProgressManager::Decrement(std::string title) {
10398
std::lock_guard<std::mutex> lock(m_progress_map_mutex);
10499
auto pos = m_progress_category_map.find(title);
105100

106-
if (pos == m_progress_category_map.end())
101+
if (pos == m_progress_category_map.end() || pos->second == 0)
107102
return;
108103

109-
// Remove the category from the map if the refcount reaches 0
104+
// Remove the category from the map if the refcount reaches 0.
110105
if (--pos->second == 0)
111106
m_progress_category_map.erase(title);
112107
}

0 commit comments

Comments
 (0)