[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