From 39d0ab32438910a0e11a64687146e2023835a93c Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Thu, 29 Mar 2012 01:41:38 +0000 Subject: [PATCH] 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 --- lldb/include/lldb/Target/Thread.h | 20 ++++++------ lldb/source/Target/Thread.cpp | 52 +++++++++++++++++++------------ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index c03d298a2681..172a9f224b8a 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -320,13 +320,13 @@ public: 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 @@ public: 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 @@ protected: virtual lldb_private::Unwind * GetUnwinder (); - StackFrameList & + lldb::StackFrameListSP GetStackFrameList (); lldb::StateType GetTemporaryResumeState() @@ -832,6 +833,7 @@ protected: 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 1000b69251d7..6a86a3b435bf 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -54,6 +54,7 @@ Thread::Thread (const ProcessSP &process_sp, lldb::tid_t tid) : 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 @@ Thread::CalculateExecutionContext (ExecutionContext &exe_ctx) } -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 @@ Thread::ClearStackFrames () lldb::StackFrameSP Thread::GetFrameWithConcreteFrameIndex (uint32_t unwind_idx) { - return GetStackFrameList().GetFrameWithConcreteFrameIndex (unwind_idx); + return GetStackFrameList()->GetFrameWithConcreteFrameIndex (unwind_idx); } void @@ -1176,7 +1188,7 @@ Thread::UpdateInstanceName () 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 @@ Thread::GetStatus (Stream &strm, uint32_t start_frame, uint32_t num_frames, uint 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 @@ Thread::GetStackFrameStatus (Stream& strm, 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