diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h index 9a13371708be5..368ec51d81891 100644 --- a/lldb/include/lldb/Target/StopInfo.h +++ b/lldb/include/lldb/Target/StopInfo.h @@ -118,6 +118,19 @@ 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 + /// viewing the thread with this stop info. + 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 { + lldb::StopReason reason = GetStopReason(); + return reason != lldb::eStopReasonNone && + reason != lldb::eStopReasonHistoryBoundary && + reason != 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 369933234ccca..02ee400db0e39 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -808,30 +808,11 @@ bool Process::HandleProcessStateChangedEvent( std::lock_guard guard(thread_list.GetMutex()); ThreadSP 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 @@ -839,47 +820,16 @@ 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: - case eStopReasonHistoryBoundary: - 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: - case eStopReasonInterrupt: - 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) @@ -887,6 +837,7 @@ bool Process::HandleProcessStateChangedEvent( else if (other_thread) thread_list.SetSelectedThreadByID(other_thread->GetID()); else { + ThreadSP thread; if (curr_thread && curr_thread->IsValid()) thread = curr_thread; else @@ -5826,7 +5777,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 e9e3603e55316..f1272a723a8cb 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -1080,12 +1080,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 +1132,17 @@ 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 { + if (ThreadSP thread_sp = m_thread_wp.lock()) + return thread_sp->GetProcess()->GetUnixSignals()->GetShouldStop(m_value); + return false; + } }; // StopInfoInterrupt