diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h index 3f7e03dc316ee..41b016015ba4b 100644 --- a/lldb/include/lldb/Target/StopInfo.h +++ b/lldb/include/lldb/Target/StopInfo.h @@ -117,6 +117,17 @@ class StopInfo : public std::enable_shared_from_this { StructuredData::ObjectSP GetExtendedInfo() { return m_extended_info; } + /// Returns true if this is a stop reason that should be shown to a user when + /// stopping. + virtual bool ShouldShow() const { return IsValid(); } + + /// Returns true if this is a stop reason that should cause a thread to be + /// selected when stopping. + virtual bool ShouldSelect() const { + return GetStopReason() != lldb::eStopReasonNone && + GetStopReason() != lldb::eStopReasonInvalid; + } + static lldb::StopInfoSP CreateStopReasonWithBreakpointSiteID(Thread &thread, lldb::break_id_t break_id); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index d4a339fc4663f..1dfc6165d0dd0 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -940,30 +940,11 @@ bool Process::HandleProcessStateChangedEvent( std::lock_guard guard(thread_list.GetMutex()); curr_thread = thread_list.GetSelectedThread(); - ThreadSP thread; - StopReason curr_thread_stop_reason = eStopReasonInvalid; - bool prefer_curr_thread = false; - if (curr_thread && curr_thread->IsValid()) { - curr_thread_stop_reason = curr_thread->GetStopReason(); - switch (curr_thread_stop_reason) { - case eStopReasonNone: - case eStopReasonInvalid: - // Don't prefer the current thread if it didn't stop for a reason. - break; - case eStopReasonSignal: { - // We need to do the same computation we do for other threads - // below in case the current thread happens to be the one that - // stopped for the no-stop signal. - uint64_t signo = curr_thread->GetStopInfo()->GetValue(); - if (process_sp->GetUnixSignals()->GetShouldStop(signo)) - prefer_curr_thread = true; - } break; - default: - prefer_curr_thread = true; - break; - } + + if (curr_thread && curr_thread->IsValid()) curr_thread_stop_info_sp = curr_thread->GetStopInfo(); - } + bool prefer_curr_thread = curr_thread_stop_info_sp && + curr_thread_stop_info_sp->ShouldSelect(); if (!prefer_curr_thread) { // Prefer a thread that has just completed its plan over another @@ -971,46 +952,17 @@ bool Process::HandleProcessStateChangedEvent( ThreadSP plan_thread; ThreadSP other_thread; - const size_t num_threads = thread_list.GetSize(); - size_t i; - for (i = 0; i < num_threads; ++i) { - thread = thread_list.GetThreadAtIndex(i); - StopReason thread_stop_reason = thread->GetStopReason(); - switch (thread_stop_reason) { - case eStopReasonInvalid: - case eStopReasonNone: - break; - - case eStopReasonSignal: { - // Don't select a signal thread if we weren't going to stop at - // that signal. We have to have had another reason for stopping - // here, and the user doesn't want to see this thread. - uint64_t signo = thread->GetStopInfo()->GetValue(); - if (process_sp->GetUnixSignals()->GetShouldStop(signo)) { - if (!other_thread) - other_thread = thread; - } - break; - } - case eStopReasonTrace: - case eStopReasonBreakpoint: - case eStopReasonWatchpoint: - case eStopReasonException: - case eStopReasonExec: - case eStopReasonFork: - case eStopReasonVFork: - case eStopReasonVForkDone: - case eStopReasonThreadExiting: - case eStopReasonInstrumentation: - case eStopReasonProcessorTrace: - if (!other_thread) - other_thread = thread; - break; - case eStopReasonPlanComplete: + for (ThreadSP thread : thread_list.Threads()) { + StopInfoSP stop_info = thread->GetStopInfo(); + if (!stop_info || !stop_info->ShouldSelect()) + continue; + StopReason thread_stop_reason = stop_info->GetStopReason(); + if (thread_stop_reason == eStopReasonPlanComplete) { if (!plan_thread) plan_thread = thread; - break; } + else if (!other_thread) + other_thread = thread; } if (plan_thread) { thread_list.SetSelectedThreadByID(plan_thread->GetID()); @@ -1019,6 +971,7 @@ bool Process::HandleProcessStateChangedEvent( thread_list.SetSelectedThreadByID(other_thread->GetID()); curr_thread = other_thread; } else { + ThreadSP thread; if (curr_thread && curr_thread->IsValid()) thread = curr_thread; else { @@ -1031,6 +984,9 @@ bool Process::HandleProcessStateChangedEvent( } } + StopReason curr_thread_stop_reason = + curr_thread_stop_info_sp ? curr_thread_stop_info_sp->GetStopReason() + : eStopReasonInvalid; check_for_repl_breakpoint = prefer_curr_thread ? IsDebuggerCausedStop(curr_thread_stop_reason) : AnyDebuggerCausedStop(thread_list); @@ -5940,7 +5896,7 @@ size_t Process::GetThreadStatus(Stream &strm, if (thread_sp) { if (only_threads_with_stop_reason) { StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); - if (!stop_info_sp || !stop_info_sp->IsValid()) + if (!stop_info_sp || !stop_info_sp->ShouldShow()) continue; } thread_sp->GetStatus(strm, start_frame, num_frames, diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index bd086550f4d82..92dee8be3bf10 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -263,6 +263,10 @@ class StopInfoBreakpoint : public StopInfo { return bp_site_sp->GetSuggestedStackFrameIndex(); } + bool ShouldShow() const override { return !m_was_all_internal; } + + bool ShouldSelect() const override { return !m_was_all_internal; } + protected: bool ShouldStop(Event *event_ptr) override { // This just reports the work done by PerformAction or the synchronous @@ -1080,12 +1084,7 @@ class StopInfoUnixSignal : public StopInfo { return false; } - bool ShouldStop(Event *event_ptr) override { - ThreadSP thread_sp(m_thread_wp.lock()); - if (thread_sp) - return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); - return false; - } + bool ShouldStop(Event *event_ptr) override { return IsShouldStopSignal(); } // If should stop returns false, check if we should notify of this event bool DoShouldNotify(Event *event_ptr) override { @@ -1137,9 +1136,18 @@ class StopInfoUnixSignal : public StopInfo { return m_description.c_str(); } + bool ShouldSelect() const override { return IsShouldStopSignal(); } + private: // In siginfo_t terms, if m_value is si_signo, m_code is si_code. std::optional m_code; + + bool IsShouldStopSignal() const { + ThreadSP thread_sp(m_thread_wp.lock()); + if (thread_sp) + return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); + return false; + } }; // StopInfoTrace