<rdar://problem/11035349> 

Fixed an issue with stepping where the stack frame list could get changed out from underneath you when multiple threads start accessing frame info.

llvm-svn: 153627
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index c03d298..172a9f2 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -320,13 +320,13 @@
     virtual uint32_t
     GetStackFrameCount()
     {
-        return GetStackFrameList().GetNumFrames();
+        return GetStackFrameList()->GetNumFrames();
     }
 
     virtual lldb::StackFrameSP
     GetStackFrameAtIndex (uint32_t idx)
     {
-        return GetStackFrameList().GetFrameAtIndex(idx);
+        return GetStackFrameList()->GetFrameAtIndex(idx);
     }
     
     virtual lldb::StackFrameSP
@@ -335,37 +335,38 @@
     virtual lldb::StackFrameSP
     GetFrameWithStackID (const StackID &stack_id)
     {
-        return GetStackFrameList().GetFrameWithStackID (stack_id);
+        return GetStackFrameList()->GetFrameWithStackID (stack_id);
     }
 
     uint32_t
     GetSelectedFrameIndex ()
     {
-        return GetStackFrameList().GetSelectedFrameIndex();
+        return GetStackFrameList()->GetSelectedFrameIndex();
     }
 
     lldb::StackFrameSP
     GetSelectedFrame ()
     {
-        return GetStackFrameAtIndex (GetStackFrameList().GetSelectedFrameIndex());
+        lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList());
+        return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex());
     }
 
     uint32_t
     SetSelectedFrame (lldb_private::StackFrame *frame)
     {
-        return GetStackFrameList().SetSelectedFrame(frame);
+        return GetStackFrameList()->SetSelectedFrame(frame);
     }
 
     bool
     SetSelectedFrameByIndex (uint32_t frame_idx)
     {
-        return GetStackFrameList().SetSelectedFrameByIndex(frame_idx);
+        return GetStackFrameList()->SetSelectedFrameByIndex(frame_idx);
     }
 
     void
     SetDefaultFileAndLineToSelectedFrame()
     {
-        GetStackFrameList().SetDefaultFileAndLineToSelectedFrame();
+        GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame();
     }
 
     virtual lldb::RegisterContextSP
@@ -798,7 +799,7 @@
     virtual lldb_private::Unwind *
     GetUnwinder ();
 
-    StackFrameList &
+    lldb::StackFrameListSP
     GetStackFrameList ();
     
     lldb::StateType GetTemporaryResumeState()
@@ -832,6 +833,7 @@
     plan_stack          m_plan_stack;           ///< The stack of plans this thread is executing.
     plan_stack          m_completed_plan_stack; ///< Plans that have been completed by this stop.  They get deleted when the thread resumes.
     plan_stack          m_discarded_plan_stack; ///< Plans that have been discarded by this stop.  They get deleted when the thread resumes.
+    mutable Mutex       m_frame_mutex;          ///< Multithreaded protection for m_state.
     lldb::StackFrameListSP m_curr_frames_sp;    ///< The stack frames that get lazily populated after a thread stops.
     lldb::StackFrameListSP m_prev_frames_sp;    ///< The previous stack frames from the last time this thread stopped.
     int                 m_resume_signal;        ///< The signal that should be used when continuing this thread.
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 1000b69..6a86a3b 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -54,6 +54,7 @@
     m_state_mutex (Mutex::eMutexTypeRecursive),
     m_plan_stack (),
     m_completed_plan_stack(),
+    m_frame_mutex (Mutex::eMutexTypeRecursive),
     m_curr_frames_sp (),
     m_prev_frames_sp (),
     m_resume_signal (LLDB_INVALID_SIGNAL_NUMBER),
@@ -1058,17 +1059,28 @@
 }
 
 
-StackFrameList &
+StackFrameListSP
 Thread::GetStackFrameList ()
 {
-    if (!m_curr_frames_sp)
-        m_curr_frames_sp.reset (new StackFrameList (*this, m_prev_frames_sp, true));
-    return *m_curr_frames_sp;
+    StackFrameListSP frame_list_sp;
+    Mutex::Locker locker(m_frame_mutex);
+    if (m_curr_frames_sp)
+    {
+        frame_list_sp = m_curr_frames_sp;
+    }
+    else
+    {
+        frame_list_sp.reset(new StackFrameList (*this, m_prev_frames_sp, true));
+        m_curr_frames_sp = frame_list_sp;
+    }
+    return frame_list_sp;
 }
 
 void
 Thread::ClearStackFrames ()
 {
+    Mutex::Locker locker(m_frame_mutex);
+
     // Only store away the old "reference" StackFrameList if we got all its frames:
     // FIXME: At some point we can try to splice in the frames we have fetched into
     // the new frame as we make it, but let's not try that now.
@@ -1080,7 +1092,7 @@
 lldb::StackFrameSP
 Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx)
 {
-    return GetStackFrameList().GetFrameWithConcreteFrameIndex (unwind_idx);
+    return GetStackFrameList()->GetFrameWithConcreteFrameIndex (unwind_idx);
 }
 
 void
@@ -1176,7 +1188,7 @@
 lldb::StackFrameSP
 Thread::GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr)
 {
-    return GetStackFrameList().GetStackFrameSPForStackFramePtr (stack_frame_ptr);
+    return GetStackFrameList()->GetStackFrameSPForStackFramePtr (stack_frame_ptr);
 }
 
 const char *
@@ -1253,13 +1265,13 @@
         const uint32_t source_lines_before = 3;
         const uint32_t source_lines_after = 3;
         strm.IndentMore ();
-        num_frames_shown = GetStackFrameList ().GetStatus (strm, 
-                                                           start_frame, 
-                                                           num_frames, 
-                                                           show_frame_info, 
-                                                           num_frames_with_source,
-                                                           source_lines_before,
-                                                           source_lines_after);
+        num_frames_shown = GetStackFrameList ()->GetStatus (strm,
+                                                            start_frame, 
+                                                            num_frames, 
+                                                            show_frame_info, 
+                                                            num_frames_with_source,
+                                                            source_lines_before,
+                                                            source_lines_after);
         strm.IndentLess();
         strm.IndentLess();
     }
@@ -1275,13 +1287,13 @@
                              uint32_t source_lines_before,
                              uint32_t source_lines_after)
 {
-    return GetStackFrameList().GetStatus (strm, 
-                                          first_frame,
-                                          num_frames,
-                                          show_frame_info,
-                                          num_frames_with_source,
-                                          source_lines_before,
-                                          source_lines_after);
+    return GetStackFrameList()->GetStatus (strm,
+                                           first_frame,
+                                           num_frames,
+                                           show_frame_info,
+                                           num_frames_with_source,
+                                           source_lines_before,
+                                           source_lines_after);
 }
 
 bool