[Lldb-commits] [lldb] Single thread stepping timeout prototype (PR #85260)

via lldb-commits lldb-commits at lists.llvm.org
Thu Mar 14 09:25:44 PDT 2024


https://github.com/jeffreytan81 created https://github.com/llvm/llvm-project/pull/85260

None

>From 6cccde22723157260e7c0b19bf8372aae8d1afaa Mon Sep 17 00:00:00 2001
From: jeffreytan81 <jeffreytan at fb.com>
Date: Wed, 6 Mar 2024 12:07:03 -0800
Subject: [PATCH 1/2] Fix strcmp build error on buildbot

---
 lldb/test/API/functionalities/fork/concurrent_vfork/main.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lldb/test/API/functionalities/fork/concurrent_vfork/main.cpp b/lldb/test/API/functionalities/fork/concurrent_vfork/main.cpp
index b0a4446ba01581..40cb63755ee8a5 100644
--- a/lldb/test/API/functionalities/fork/concurrent_vfork/main.cpp
+++ b/lldb/test/API/functionalities/fork/concurrent_vfork/main.cpp
@@ -1,6 +1,7 @@
 #include <assert.h>
 #include <iostream>
 #include <mutex>
+#include <string.h>
 #include <sys/wait.h>
 #include <thread>
 #include <unistd.h>

>From 6982a47579b372b0e34c751c9952b4aa03531aeb Mon Sep 17 00:00:00 2001
From: jeffreytan81 <jeffreytan at fb.com>
Date: Thu, 14 Mar 2024 09:24:58 -0700
Subject: [PATCH 2/2] Single thread timeout prototype

---
 lldb/include/lldb/Target/ThreadPlan.h         |   3 +-
 .../Target/ThreadPlanSingleThreadTimeout.h    | 134 ++++++++++++++++++
 .../lldb/Target/ThreadPlanStepOverRange.h     |   2 +
 .../source/Target/ThreadPlanStepOverRange.cpp |  14 +-
 4 files changed, 151 insertions(+), 2 deletions(-)
 create mode 100644 lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h

diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index bf68a42e54d18f..3b488841bd9010 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -302,7 +302,8 @@ class ThreadPlan : public std::enable_shared_from_this<ThreadPlan>,
     eKindStepInRange,
     eKindRunToAddress,
     eKindStepThrough,
-    eKindStepUntil
+    eKindStepUntil,
+    eKindSingleThreadTimeout
   };
 
   virtual ~ThreadPlan();
diff --git a/lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h b/lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h
new file mode 100644
index 00000000000000..a7b8b4ffaa8c40
--- /dev/null
+++ b/lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h
@@ -0,0 +1,134 @@
+//===-- ThreadPlanSingleThreadTimeout.h -------------------------------------*-
+// C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// TODO
+#ifndef LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
+#define LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/State.h"
+
+#include <thread>
+
+namespace lldb_private {
+
+enum class SingleThreadPlanTimeoutState {
+  InitialResume,
+  TimeoutHalt,
+  ResumingAllThreads,
+  AfterThreadResumed,
+};
+
+class ThreadPlanSingleThreadTimeout : public ThreadPlan {
+public:
+  ThreadPlanSingleThreadTimeout(Thread &thread)
+      : ThreadPlan(ThreadPlan::eKindSingleThreadTimeout,
+                   "Single thread timeout", thread, eVoteNo, eVoteNoOpinion),
+        m_state(SingleThreadPlanTimeoutState::InitialResume) {
+    std::thread t(thread_function, this);
+    t.detach();
+  }
+
+  ~ThreadPlanSingleThreadTimeout() override = default;
+
+  void GetDescription(Stream *s, lldb::DescriptionLevel level) override {
+    s->Printf("SingleThreadPlanTimeout, state(%d)", (int)m_state);
+  }
+  bool ValidatePlan(Stream *error) override { return true; }
+  bool WillStop() override { return true; }
+  bool DoPlanExplainsStop(Event *event_ptr) override { return true; }
+  lldb::StateType GetPlanRunState() override { return lldb::eStateRunning; }
+  static void thread_function(ThreadPlanSingleThreadTimeout *self) {
+    int timeout_ms = 5000; // 5 seconds timeout
+    std::this_thread::sleep_for(
+        std::chrono::milliseconds(timeout_ms));
+    self->HandleTimeout();
+  }
+
+  bool MischiefManaged() override {
+    // return m_state == SingleThreadPlanTimeoutState::AfterThreadResumed;
+    return GetPreviousPlan()->MischiefManaged();
+  }
+
+  bool ShouldStop(Event *event_ptr) override {
+    if (m_state == SingleThreadPlanTimeoutState::InitialResume) {
+      return GetPreviousPlan()->ShouldStop(event_ptr);
+    }
+    return HandleEvent(event_ptr);
+  }
+
+  void SetStopOthers(bool new_value) override {
+    GetPreviousPlan()->SetStopOthers(new_value);
+  }
+
+  bool StopOthers() override {
+    if (m_state == SingleThreadPlanTimeoutState::ResumingAllThreads ||
+        m_state == SingleThreadPlanTimeoutState::AfterThreadResumed)
+      return false;
+    else
+      return GetPreviousPlan()->StopOthers();
+  }
+
+protected:
+  bool DoWillResume(lldb::StateType resume_state, bool current_plan) override {
+    if (m_state == SingleThreadPlanTimeoutState::ResumingAllThreads) {
+      m_state = SingleThreadPlanTimeoutState::AfterThreadResumed;
+    }
+    return GetPreviousPlan()->WillResume(resume_state, current_plan);
+  }
+
+  bool HandleEvent(Event *event_ptr) {
+    lldb::StateType stop_state =
+        Process::ProcessEventData::GetStateFromEvent(event_ptr);
+    Log *log = GetLog(LLDBLog::Step);
+    LLDB_LOGF(log,
+              "ThreadPlanSingleThreadTimeout::HandleEvent(): got event: %s.",
+              StateAsCString(stop_state));
+
+    bool should_stop = true;
+    if (m_state == SingleThreadPlanTimeoutState::TimeoutHalt &&
+        stop_state == lldb::eStateStopped) {
+      if (Process::ProcessEventData::GetRestartedFromEvent(event_ptr)) {
+        // If we were restarted, we just need to go back up to fetch
+        // another event.
+        LLDB_LOGF(
+            log, "ThreadPlanSingleThreadTimeout::HandleEvent(): Got a stop and "
+                 "restart, so we'll continue waiting.");
+
+      } else {
+        GetThread().GetCurrentPlan()->SetStopOthers(false);
+        m_state = SingleThreadPlanTimeoutState::ResumingAllThreads;
+      }
+      should_stop = false;
+    }
+    if (should_stop)
+      return GetPreviousPlan()->ShouldStop(event_ptr);
+    else
+      return false;
+  }
+
+  void HandleTimeout() {
+    m_state = SingleThreadPlanTimeoutState::TimeoutHalt;
+    m_process.SendAsyncInterrupt();
+  }
+
+private:
+  SingleThreadPlanTimeoutState m_state;
+
+  ThreadPlanSingleThreadTimeout(const ThreadPlanSingleThreadTimeout &) = delete;
+  const ThreadPlanSingleThreadTimeout &
+  operator=(const ThreadPlanSingleThreadTimeout &) = delete;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_TARGET_THREADPLANSINGLETHREADTIMEOUT_H
diff --git a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
index 8585ac62f09b35..c895620eb85f53 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h
@@ -28,6 +28,7 @@ class ThreadPlanStepOverRange : public ThreadPlanStepRange,
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
   bool ShouldStop(Event *event_ptr) override;
+  void DidPush() override;
 
 protected:
   bool DoPlanExplainsStop(Event *event_ptr) override;
@@ -44,6 +45,7 @@ class ThreadPlanStepOverRange : public ThreadPlanStepRange,
   bool IsEquivalentContext(const SymbolContext &context);
 
   bool m_first_resume;
+  lldb::RunMode m_run_mode;
 
   ThreadPlanStepOverRange(const ThreadPlanStepOverRange &) = delete;
   const ThreadPlanStepOverRange &
diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp
index 84f282f1de5207..17edc6ba3cfeb5 100644
--- a/lldb/source/Target/ThreadPlanStepOverRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanSingleThreadTimeout.h"
 #include "lldb/Target/ThreadPlanStepOut.h"
 #include "lldb/Target/ThreadPlanStepThrough.h"
 #include "lldb/Utility/LLDBLog.h"
@@ -36,13 +37,24 @@ ThreadPlanStepOverRange::ThreadPlanStepOverRange(
     : ThreadPlanStepRange(ThreadPlan::eKindStepOverRange,
                           "Step range stepping over", thread, range,
                           addr_context, stop_others),
-      ThreadPlanShouldStopHere(this), m_first_resume(true) {
+      ThreadPlanShouldStopHere(this), m_first_resume(true),
+      m_run_mode(stop_others) {
   SetFlagsToDefault();
   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
 }
 
 ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
 
+void ThreadPlanStepOverRange::DidPush() {
+  if (m_run_mode == lldb::eOnlyThisThread) {
+    Thread &thread = GetThread();
+    auto timeout_plan = new ThreadPlanSingleThreadTimeout(thread);
+    ThreadPlanSP thread_plan_sp(timeout_plan);
+    auto status = thread.QueueThreadPlan(thread_plan_sp,
+                                         /*abort_other_plans*/ false);
+  }
+}
+
 void ThreadPlanStepOverRange::GetDescription(Stream *s,
                                              lldb::DescriptionLevel level) {
   auto PrintFailureIfAny = [&]() {



More information about the lldb-commits mailing list