[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