Add a mutex lock to StackFrame to protect race conditions for

updating its ivars.  We've had a lot of crash reports and careful
analysis shows that we've got multiple threads operating on the
same StackFrame objects, changing their m_sc and m_flags ivars.
<rdar://problem/18406111> 

llvm-svn: 218845
This commit is contained in:
Jason Molenda 2014-10-02 01:08:16 +00:00
parent 78b833bb53
commit 6a35470563
2 changed files with 21 additions and 3 deletions

View File

@ -519,6 +519,7 @@ private:
lldb::VariableListSP m_variable_list_sp;
ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp
StreamString m_disassembly;
Mutex m_mutex;
DISALLOW_COPY_AND_ASSIGN (StackFrame);
};

View File

@ -70,7 +70,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_is_history_frame (is_history_frame),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
m_disassembly (),
m_mutex (Mutex::eMutexTypeRecursive)
{
// If we don't have a CFA value, use the frame index for our StackID so that recursive
// functions properly aren't confused with one another on a history stack.
@ -109,7 +110,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_is_history_frame (false),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
m_disassembly (),
m_mutex (Mutex::eMutexTypeRecursive)
{
if (sc_ptr != NULL)
{
@ -148,7 +150,8 @@ StackFrame::StackFrame (const ThreadSP &thread_sp,
m_is_history_frame (false),
m_variable_list_sp (),
m_variable_list_value_objects (),
m_disassembly ()
m_disassembly (),
m_mutex (Mutex::eMutexTypeRecursive)
{
if (sc_ptr != NULL)
{
@ -189,6 +192,7 @@ StackFrame::~StackFrame()
StackID&
StackFrame::GetStackID()
{
Mutex::Locker locker(m_mutex);
// Make sure we have resolved the StackID object's symbol context scope if
// we already haven't looked it up.
@ -235,6 +239,7 @@ StackFrame::GetFrameIndex () const
void
StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
{
Mutex::Locker locker(m_mutex);
m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
m_id.SetSymbolContextScope (symbol_scope);
}
@ -242,6 +247,7 @@ StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
const Address&
StackFrame::GetFrameCodeAddress()
{
Mutex::Locker locker(m_mutex);
if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset())
{
m_flags.Set (RESOLVED_FRAME_CODE_ADDR);
@ -272,6 +278,7 @@ StackFrame::GetFrameCodeAddress()
bool
StackFrame::ChangePC (addr_t pc)
{
Mutex::Locker locker(m_mutex);
// We can't change the pc value of a history stack frame - it is immutable.
if (m_is_history_frame)
return false;
@ -287,6 +294,7 @@ StackFrame::ChangePC (addr_t pc)
const char *
StackFrame::Disassemble ()
{
Mutex::Locker locker(m_mutex);
if (m_disassembly.GetSize() == 0)
{
ExecutionContext exe_ctx (shared_from_this());
@ -346,6 +354,7 @@ StackFrame::GetFrameBlock ()
const SymbolContext&
StackFrame::GetSymbolContext (uint32_t resolve_scope)
{
Mutex::Locker locker(m_mutex);
// Copy our internal symbol context into "sc".
if ((m_flags.Get() & resolve_scope) != resolve_scope)
{
@ -504,6 +513,7 @@ StackFrame::GetSymbolContext (uint32_t resolve_scope)
VariableList *
StackFrame::GetVariableList (bool get_file_globals)
{
Mutex::Locker locker(m_mutex);
if (m_flags.IsClear(RESOLVED_VARIABLES))
{
m_flags.Set(RESOLVED_VARIABLES);
@ -544,6 +554,7 @@ StackFrame::GetVariableList (bool get_file_globals)
VariableListSP
StackFrame::GetInScopeVariableList (bool get_file_globals)
{
Mutex::Locker locker(m_mutex);
// We can't fetch variable information for a history stack frame.
if (m_is_history_frame)
return VariableListSP();
@ -1142,6 +1153,7 @@ StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
bool
StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
{
Mutex::Locker locker(m_mutex);
if (m_cfa_is_valid == false)
{
m_frame_base_error.SetErrorString("No frame base available for this historical stack frame.");
@ -1191,6 +1203,7 @@ StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
RegisterContextSP
StackFrame::GetRegisterContext ()
{
Mutex::Locker locker(m_mutex);
if (!m_reg_context_sp)
{
ThreadSP thread_sp (GetThread());
@ -1211,6 +1224,7 @@ StackFrame::HasDebugInformation ()
ValueObjectSP
StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
{
Mutex::Locker locker(m_mutex);
ValueObjectSP valobj_sp;
if (m_is_history_frame)
{
@ -1246,6 +1260,7 @@ StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, Dynam
ValueObjectSP
StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
{
Mutex::Locker locker(m_mutex);
if (m_is_history_frame)
return ValueObjectSP();
@ -1376,6 +1391,7 @@ StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths)
void
StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
{
Mutex::Locker locker(m_mutex);
assert (GetStackID() == prev_frame.GetStackID()); // TODO: remove this after some testing
m_variable_list_sp = prev_frame.m_variable_list_sp;
m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects);
@ -1387,6 +1403,7 @@ StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
void
StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame)
{
Mutex::Locker locker(m_mutex);
assert (GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing
m_id.SetPC (curr_frame.m_id.GetPC()); // Update the Stack ID PC value
assert (GetThread() == curr_frame.GetThread());