Skip to content

Commit f97f17e

Browse files
committed
[lldb] Synchronize access to m_statusline in the Debugger
Eliminate a potential race between the main thread and the default event handler thread when accessing the m_statusline member. Some methods could be called from a signal handler and are allowed to fail locking.
1 parent 9b63a92 commit f97f17e

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

lldb/include/lldb/Core/Debugger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
751751
IOHandlerStack m_io_handler_stack;
752752
std::recursive_mutex m_io_handler_synchronous_mutex;
753753

754+
std::mutex m_statusline_mutex;
754755
std::optional<Statusline> m_statusline;
755756

756757
llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers;

lldb/source/Core/Debugger.cpp

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
251251
g_debugger_properties[ePropertyShowStatusline].name) {
252252
// Statusline setting changed. If we have a statusline instance, update it
253253
// now. Otherwise it will get created in the default event handler.
254+
std::lock_guard<std::mutex> guard(m_statusline_mutex);
254255
if (StatuslineSupported())
255256
m_statusline.emplace(*this);
256257
else
@@ -391,8 +392,13 @@ bool Debugger::SetTerminalWidth(uint64_t term_width) {
391392

392393
if (auto handler_sp = m_io_handler_stack.Top())
393394
handler_sp->TerminalSizeChanged();
394-
if (m_statusline)
395-
m_statusline->TerminalSizeChanged();
395+
396+
{
397+
// This might get called from a signal handler.
398+
std::unique_lock<std::mutex> lock(m_statusline_mutex, std::try_to_lock);
399+
if (m_statusline)
400+
m_statusline->TerminalSizeChanged();
401+
}
396402

397403
return success;
398404
}
@@ -409,8 +415,13 @@ bool Debugger::SetTerminalHeight(uint64_t term_height) {
409415

410416
if (auto handler_sp = m_io_handler_stack.Top())
411417
handler_sp->TerminalSizeChanged();
412-
if (m_statusline)
413-
m_statusline->TerminalSizeChanged();
418+
419+
{
420+
// This might get called from a signal handler.
421+
std::unique_lock<std::mutex> lock(m_statusline_mutex, std::try_to_lock);
422+
if (m_statusline)
423+
m_statusline->TerminalSizeChanged();
424+
}
414425

415426
return success;
416427
}
@@ -1141,20 +1152,29 @@ void Debugger::SetErrorFile(FileSP file_sp) {
11411152
}
11421153

11431154
void Debugger::SaveInputTerminalState() {
1144-
if (m_statusline)
1145-
m_statusline->Disable();
1155+
{
1156+
// This might get called from a signal handler.
1157+
std::unique_lock<std::mutex> lock(m_statusline_mutex, std::try_to_lock);
1158+
if (m_statusline)
1159+
m_statusline->Disable();
1160+
}
11461161
int fd = GetInputFile().GetDescriptor();
11471162
if (fd != File::kInvalidDescriptor)
11481163
m_terminal_state.Save(fd, true);
11491164
}
11501165

11511166
void Debugger::RestoreInputTerminalState() {
11521167
m_terminal_state.Restore();
1153-
if (m_statusline)
1154-
m_statusline->Enable();
1168+
{
1169+
// This might get called from a signal handler.
1170+
std::unique_lock<std::mutex> lock(m_statusline_mutex, std::try_to_lock);
1171+
if (m_statusline)
1172+
m_statusline->Enable();
1173+
}
11551174
}
11561175

11571176
void Debugger::RedrawStatusline(bool update) {
1177+
std::lock_guard<std::mutex> guard(m_statusline_mutex);
11581178
if (m_statusline)
11591179
m_statusline->Redraw(update);
11601180
}
@@ -2032,8 +2052,11 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
20322052
// are now listening to all required events so no events get missed
20332053
m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
20342054

2035-
if (!m_statusline && StatuslineSupported())
2036-
m_statusline.emplace(*this);
2055+
if (StatuslineSupported()) {
2056+
std::lock_guard<std::mutex> guard(m_statusline_mutex);
2057+
if (!m_statusline)
2058+
m_statusline.emplace(*this);
2059+
}
20372060

20382061
bool done = false;
20392062
while (!done) {
@@ -2094,8 +2117,11 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
20942117
}
20952118
}
20962119

2097-
if (m_statusline)
2098-
m_statusline.reset();
2120+
{
2121+
std::lock_guard<std::mutex> guard(m_statusline_mutex);
2122+
if (m_statusline)
2123+
m_statusline.reset();
2124+
}
20992125

21002126
return {};
21012127
}

0 commit comments

Comments
 (0)