[Lldb-commits] [lldb] r268563 - Don't let two threads call Debugger::Clear simultaneously.
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Wed May 4 15:26:43 PDT 2016
Author: gclayton
Date: Wed May 4 17:26:42 2016
New Revision: 268563
URL: http://llvm.org/viewvc/llvm-project?rev=268563&view=rev
Log:
Don't let two threads call Debugger::Clear simultaneously.
We don't want a mutex in debugger as it will cause A/B locking issues with the lldb_private::Target's mutex, but we do need to stop two threads from doing Debugger::Clear at the same time. We have seen issues with this with the C++ global destructor chain where the global debugger list is being destroyed and the Debugger::~Debugger() is calling it while another thread was in the middle of running that function.
<rdar://problem/26098913>
Modified:
lldb/trunk/include/lldb/Core/Debugger.h
lldb/trunk/source/Core/Debugger.cpp
Modified: lldb/trunk/include/lldb/Core/Debugger.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=268563&r1=268562&r2=268563&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Debugger.h (original)
+++ lldb/trunk/include/lldb/Core/Debugger.h Wed May 4 17:26:42 2016
@@ -482,6 +482,7 @@ protected:
HostThread m_io_handler_thread;
Broadcaster m_sync_broadcaster;
lldb::ListenerSP m_forward_listener_sp;
+ std::once_flag m_clear_once;
//----------------------------------------------------------------------
// Events for m_sync_broadcaster
Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=268563&r1=268562&r2=268563&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Wed May 4 17:26:42 2016
@@ -715,7 +715,9 @@ Debugger::Debugger(lldb::LogOutputCallba
m_loaded_plugins(),
m_event_handler_thread(),
m_io_handler_thread(),
- m_sync_broadcaster(nullptr, "lldb.debugger.sync")
+ m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
+ m_forward_listener_sp(),
+ m_clear_once()
{
char instance_cstr[256];
snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
@@ -762,31 +764,44 @@ Debugger::~Debugger ()
void
Debugger::Clear()
{
- ClearIOHandlers();
- StopIOHandlerThread();
- StopEventHandlerThread();
- m_listener_sp->Clear();
- int num_targets = m_target_list.GetNumTargets();
- for (int i = 0; i < num_targets; i++)
- {
- TargetSP target_sp (m_target_list.GetTargetAtIndex (i));
- if (target_sp)
+ //----------------------------------------------------------------------
+ // Make sure we call this function only once. With the C++ global
+ // destructor chain having a list of debuggers and with code that can be
+ // running on other threads, we need to ensure this doesn't happen
+ // multiple times.
+ //
+ // The following functions call Debugger::Clear():
+ // Debugger::~Debugger();
+ // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
+ // static void Debugger::Terminate();
+ //----------------------------------------------------------------------
+ std::call_once(m_clear_once, [this]() {
+ ClearIOHandlers();
+ StopIOHandlerThread();
+ StopEventHandlerThread();
+ m_listener_sp->Clear();
+ int num_targets = m_target_list.GetNumTargets();
+ for (int i = 0; i < num_targets; i++)
{
- ProcessSP process_sp (target_sp->GetProcessSP());
- if (process_sp)
- process_sp->Finalize();
- target_sp->Destroy();
+ TargetSP target_sp (m_target_list.GetTargetAtIndex (i));
+ if (target_sp)
+ {
+ ProcessSP process_sp (target_sp->GetProcessSP());
+ if (process_sp)
+ process_sp->Finalize();
+ target_sp->Destroy();
+ }
}
- }
- m_broadcaster_manager_sp->Clear ();
-
- // Close the input file _before_ we close the input read communications class
- // as it does NOT own the input file, our m_input_file does.
- m_terminal_state.Clear();
- if (m_input_file_sp)
- m_input_file_sp->GetFile().Close ();
-
- m_command_interpreter_ap->Clear();
+ m_broadcaster_manager_sp->Clear ();
+
+ // Close the input file _before_ we close the input read communications class
+ // as it does NOT own the input file, our m_input_file does.
+ m_terminal_state.Clear();
+ if (m_input_file_sp)
+ m_input_file_sp->GetFile().Close ();
+
+ m_command_interpreter_ap->Clear();
+ });
}
bool
More information about the lldb-commits
mailing list