[Lldb-commits] [lldb] d3dfd8c - Add a setting to force stepping to always run all threads.
Jim Ingham via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 7 14:47:42 PDT 2020
Author: Jim Ingham
Date: 2020-08-07T14:47:31-07:00
New Revision: d3dfd8cec44072302818c34193d898903dbaef8f
URL: https://github.com/llvm/llvm-project/commit/d3dfd8cec44072302818c34193d898903dbaef8f
DIFF: https://github.com/llvm/llvm-project/commit/d3dfd8cec44072302818c34193d898903dbaef8f.diff
LOG: Add a setting to force stepping to always run all threads.
Also allow ScriptedThreadPlans to set & get their StopOthers
state.
<rdar://problem/64229484>
Differential Revision: https://reviews.llvm.org/D85265
Added:
Modified:
lldb/bindings/interface/SBThreadPlan.i
lldb/include/lldb/API/SBThreadPlan.h
lldb/include/lldb/Target/Process.h
lldb/include/lldb/Target/ThreadPlanPython.h
lldb/source/API/SBThreadPlan.cpp
lldb/source/Commands/CommandObjectThread.cpp
lldb/source/Target/Process.cpp
lldb/source/Target/TargetProperties.td
lldb/source/Target/Thread.cpp
lldb/source/Target/ThreadPlanPython.cpp
lldb/test/API/functionalities/step_scripted/Steps.py
lldb/test/API/functionalities/step_scripted/TestStepScripted.py
Removed:
################################################################################
diff --git a/lldb/bindings/interface/SBThreadPlan.i b/lldb/bindings/interface/SBThreadPlan.i
index 36131d529b7b..2003c6fdee3a 100644
--- a/lldb/bindings/interface/SBThreadPlan.i
+++ b/lldb/bindings/interface/SBThreadPlan.i
@@ -92,6 +92,14 @@ public:
bool
IsPlanStale();
+ %feature("docstring", "Return whether this plan will ask to stop other threads when it runs.") GetStopOthers;
+ bool
+ GetStopOthers();
+
+ %feature("docstring", "Set whether this plan will ask to stop other threads when it runs.") GetStopOthers;
+ void
+ SetStopOthers(bool stop_others);
+
SBThreadPlan
QueueThreadPlanForStepOverRange (SBAddress &start_address,
lldb::addr_t range_size);
diff --git a/lldb/include/lldb/API/SBThreadPlan.h b/lldb/include/lldb/API/SBThreadPlan.h
index 6639c10e437b..0dc48437a668 100644
--- a/lldb/include/lldb/API/SBThreadPlan.h
+++ b/lldb/include/lldb/API/SBThreadPlan.h
@@ -77,6 +77,10 @@ class LLDB_API SBThreadPlan {
bool IsValid();
+ bool GetStopOthers();
+
+ void SetStopOthers(bool stop_others);
+
// This section allows an SBThreadPlan to push another of the common types of
// plans...
SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index bf9b64547ed5..2abedb8f6e2e 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -91,6 +91,7 @@ class ProcessProperties : public Properties {
std::chrono::seconds GetUtilityExpressionTimeout() const;
bool GetOSPluginReportsAllThreads() const;
void SetOSPluginReportsAllThreads(bool does_report);
+ bool GetSteppingRunsAllThreads() const;
protected:
Process *m_process; // Can be nullptr for global ProcessProperties
diff --git a/lldb/include/lldb/Target/ThreadPlanPython.h b/lldb/include/lldb/Target/ThreadPlanPython.h
index 27bf3a560b1f..c04500ad5de8 100644
--- a/lldb/include/lldb/Target/ThreadPlanPython.h
+++ b/lldb/include/lldb/Target/ThreadPlanPython.h
@@ -45,7 +45,9 @@ class ThreadPlanPython : public ThreadPlan {
bool WillStop() override;
- bool StopOthers() override;
+ bool StopOthers() override { return m_stop_others; }
+
+ void SetStopOthers(bool new_value) { m_stop_others = new_value; }
void DidPush() override;
@@ -67,6 +69,7 @@ class ThreadPlanPython : public ThreadPlan {
std::string m_error_str;
StructuredData::ObjectSP m_implementation_sp;
bool m_did_push;
+ bool m_stop_others;
ThreadPlanPython(const ThreadPlanPython &) = delete;
const ThreadPlanPython &operator=(const ThreadPlanPython &) = delete;
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
index c740c8b7492f..9af673b0f3a9 100644
--- a/lldb/source/API/SBThreadPlan.cpp
+++ b/lldb/source/API/SBThreadPlan.cpp
@@ -196,6 +196,23 @@ bool SBThreadPlan::IsValid() {
return false;
}
+bool SBThreadPlan::GetStopOthers() {
+ LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, GetStopOthers);
+
+ ThreadPlanSP thread_plan_sp(GetSP());
+ if (thread_plan_sp)
+ return thread_plan_sp->StopOthers();
+ return false;
+}
+
+void SBThreadPlan::SetStopOthers(bool stop_others) {
+ LLDB_RECORD_METHOD(void, SBThreadPlan, SetStopOthers, (bool), stop_others);
+
+ ThreadPlanSP thread_plan_sp(GetSP());
+ if (thread_plan_sp)
+ thread_plan_sp->SetStopOthers(stop_others);
+}
+
// This section allows an SBThreadPlan to push another of the common types of
// plans...
//
@@ -463,6 +480,8 @@ void RegisterMethods<SBThreadPlan>(Registry &R) {
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ());
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ());
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ());
+ LLDB_REGISTER_METHOD(void, SBThreadPlan, SetStopOthers, (bool));
+ LLDB_REGISTER_METHOD(bool, SBThreadPlan, GetStopOthers, ());
LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan,
QueueThreadPlanForStepOverRange,
(lldb::SBAddress &, lldb::addr_t));
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index f0ad1798fec6..666c208c3206 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -482,8 +482,16 @@ class ThreadStepScopeOptionGroup : public OptionGroup {
// Check if we are in Non-Stop mode
TargetSP target_sp =
execution_context ? execution_context->GetTargetSP() : TargetSP();
- if (target_sp && target_sp->GetNonStopModeEnabled())
+ if (target_sp && target_sp->GetNonStopModeEnabled()) {
+ // NonStopMode runs all threads by definition, so when it is on we don't
+ // need to check the process setting for runs all threads.
m_run_mode = eOnlyThisThread;
+ } else {
+ ProcessSP process_sp =
+ execution_context ? execution_context->GetProcessSP() : ProcessSP();
+ if (process_sp && process_sp->GetSteppingRunsAllThreads())
+ m_run_mode = eAllThreads;
+ }
m_avoid_regexp.clear();
m_step_in_target.clear();
@@ -612,8 +620,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
if (m_options.m_run_mode == eAllThreads)
bool_stop_other_threads = false;
else if (m_options.m_run_mode == eOnlyDuringStepping)
- bool_stop_other_threads =
- (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted);
+ bool_stop_other_threads = (m_step_type != eStepTypeOut);
else
bool_stop_other_threads = true;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e88911ad7210..c602511daedc 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -278,6 +278,12 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
return std::chrono::seconds(value);
}
+bool ProcessProperties::GetSteppingRunsAllThreads() const {
+ const uint32_t idx = ePropertySteppingRunsAllThreads;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_process_properties[idx].default_uint_value != 0);
+}
+
bool ProcessProperties::GetOSPluginReportsAllThreads() const {
const bool fail_value = true;
const Property *exp_property =
diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td
index 58aae058d5d4..7fb9b105ceef 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -217,6 +217,9 @@ let Definition = "process" in {
def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">,
DefaultUnsignedValue<15>,
Desc<"The time in seconds to wait for LLDB-internal utility expressions.">;
+ def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">,
+ DefaultFalse,
+ Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">;
}
let Definition = "platform" in {
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index ad28603cc02e..fdf60f96f983 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1380,7 +1380,7 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name,
extra_args_impl));
-
+ thread_plan_sp->SetStopOthers(stop_other_threads);
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
diff --git a/lldb/source/Target/ThreadPlanPython.cpp b/lldb/source/Target/ThreadPlanPython.cpp
index 8171186319f5..e83f0e9e715e 100644
--- a/lldb/source/Target/ThreadPlanPython.cpp
+++ b/lldb/source/Target/ThreadPlanPython.cpp
@@ -25,11 +25,12 @@ using namespace lldb_private;
// ThreadPlanPython
-ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
+ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
StructuredDataImpl *args_data)
: ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_class_name(class_name), m_args_data(args_data), m_did_push(false) {
+ m_class_name(class_name), m_args_data(args_data), m_did_push(false),
+ m_stop_others(false) {
SetIsMasterPlan(true);
SetOkayToDiscard(true);
SetPrivate(false);
@@ -162,13 +163,6 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
}
// The ones below are not currently exported to Python.
-
-bool ThreadPlanPython::StopOthers() {
- // For now Python plans run all threads, but we should add some controls for
- // this.
- return false;
-}
-
void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
s->Printf("Python thread plan implemented by class %s.",
m_class_name.c_str());
diff --git a/lldb/test/API/functionalities/step_scripted/Steps.py b/lldb/test/API/functionalities/step_scripted/Steps.py
index 4133cbbe6086..d41d01d43095 100644
--- a/lldb/test/API/functionalities/step_scripted/Steps.py
+++ b/lldb/test/API/functionalities/step_scripted/Steps.py
@@ -75,9 +75,29 @@ def should_stop(self, event):
if not self.value.IsValid():
return True
- print("Got next value: %d"%(self.value.GetValueAsUnsigned()))
if not self.value.GetValueDidChange():
self.child_thread_plan = self.queue_child_thread_plan()
return False
else:
return True
+
+# This plan does nothing, but sets stop_mode to the
+# value of GetStopOthers for this plan.
+class StepReportsStopOthers():
+ stop_mode_dict = {}
+
+ def __init__(self, thread_plan, args_data, dict):
+ self.thread_plan = thread_plan
+ self.key = args_data.GetValueForKey("token").GetStringValue(1000)
+
+ def should_stop(self, event):
+ self.thread_plan.SetPlanComplete(True)
+ print("Called in should_stop")
+ StepReportsStopOthers.stop_mode_dict[self.key] = self.thread_plan.GetStopOthers()
+ return True
+
+ def should_step(self):
+ return True
+
+ def explains_stop(self, event):
+ return True
diff --git a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
index 1e87541960c8..60eb96173765 100644
--- a/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
+++ b/lldb/test/API/functionalities/step_scripted/TestStepScripted.py
@@ -1,7 +1,7 @@
"""
Tests stepping with scripted thread plans.
"""
-
+import threading
import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.decorators import *
@@ -111,3 +111,58 @@ def do_test_checking_variable(self, use_cli):
# And foo should have changed:
self.assertTrue(foo_val.GetValueDidChange(), "Foo changed")
+
+ def test_stop_others_from_command(self):
+ """Test that the stop-others flag is set correctly by the command line.
+ Also test that the run-all-threads property overrides this."""
+ self.do_test_stop_others()
+
+ def run_step(self, stop_others_value, run_mode, token):
+ import Steps
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+
+ cmd = "thread step-scripted -C Steps.StepReportsStopOthers -k token -v %s"%(token)
+ if run_mode != None:
+ cmd = cmd + " --run-mode %s"%(run_mode)
+ print(cmd)
+ interp.HandleCommand(cmd, result)
+ self.assertTrue(result.Succeeded(), "Step scripted failed: %s."%(result.GetError()))
+ print(Steps.StepReportsStopOthers.stop_mode_dict)
+ value = Steps.StepReportsStopOthers.stop_mode_dict[token]
+ self.assertEqual(value, stop_others_value, "Stop others has the correct value.")
+
+ def do_test_stop_others(self):
+ self.build()
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ "Set a breakpoint here",
+ self.main_source_file)
+ # First run with stop others false and see that we got that.
+ thread_id = ""
+ if sys.version_info.major == 2:
+ thread_id = str(threading._get_ident())
+ else:
+ thread_id = str(threading.get_ident())
+
+ # all-threads should set stop others to False.
+ self.run_step(False, "all-threads", thread_id)
+
+ # this-thread should set stop others to True
+ self.run_step(True, "this-thread", thread_id)
+
+ # The default value should be stop others:
+ self.run_step(True, None, thread_id)
+
+ # The target.process.run-all-threads should override this:
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+
+ interp.HandleCommand("settings set target.process.run-all-threads true", result)
+ self.assertTrue(result.Succeeded, "setting run-all-threads works.")
+
+ self.run_step(False, None, thread_id)
+
+
+
+
+
More information about the lldb-commits
mailing list