Skip to content

Commit 48e913c

Browse files
authored
Merge pull request #1842 from jimingham/run-all-threads
Add a setting to force stepping to always run all threads.
2 parents 45448a1 + 9ddb091 commit 48e913c

File tree

12 files changed

+136
-16
lines changed

12 files changed

+136
-16
lines changed

lldb/bindings/interface/SBThreadPlan.i

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ public:
9292
bool
9393
IsPlanStale();
9494

95+
%feature("docstring", "Return whether this plan will ask to stop other threads when it runs.") GetStopOthers;
96+
bool
97+
GetStopOthers();
98+
99+
%feature("docstring", "Set whether this plan will ask to stop other threads when it runs.") GetStopOthers;
100+
void
101+
SetStopOthers(bool stop_others);
102+
95103
SBThreadPlan
96104
QueueThreadPlanForStepOverRange (SBAddress &start_address,
97105
lldb::addr_t range_size);

lldb/include/lldb/API/SBThreadPlan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class LLDB_API SBThreadPlan {
7777

7878
bool IsValid();
7979

80+
bool GetStopOthers();
81+
82+
void SetStopOthers(bool stop_others);
83+
8084
// This section allows an SBThreadPlan to push another of the common types of
8185
// plans...
8286
SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,

lldb/include/lldb/Target/Process.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class ProcessProperties : public Properties {
9191
std::chrono::seconds GetUtilityExpressionTimeout() const;
9292
bool GetOSPluginReportsAllThreads() const;
9393
void SetOSPluginReportsAllThreads(bool does_report);
94+
bool GetSteppingRunsAllThreads() const;
9495

9596
protected:
9697
Process *m_process; // Can be nullptr for global ProcessProperties

lldb/include/lldb/Target/ThreadPlanPython.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ class ThreadPlanPython : public ThreadPlan {
4545

4646
bool WillStop() override;
4747

48-
bool StopOthers() override;
48+
bool StopOthers() override { return m_stop_others; }
49+
50+
void SetStopOthers(bool new_value) { m_stop_others = new_value; }
4951

5052
void DidPush() override;
5153

@@ -67,6 +69,7 @@ class ThreadPlanPython : public ThreadPlan {
6769
std::string m_error_str;
6870
StructuredData::ObjectSP m_implementation_sp;
6971
bool m_did_push;
72+
bool m_stop_others;
7073

7174
ThreadPlanPython(const ThreadPlanPython &) = delete;
7275
const ThreadPlanPython &operator=(const ThreadPlanPython &) = delete;

lldb/source/API/SBThreadPlan.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,23 @@ bool SBThreadPlan::IsValid() {
196196
return false;
197197
}
198198

199+
bool SBThreadPlan::GetStopOthers() {
200+
LLDB_RECORD_METHOD_NO_ARGS(bool, SBThreadPlan, GetStopOthers);
201+
202+
ThreadPlanSP thread_plan_sp(GetSP());
203+
if (thread_plan_sp)
204+
return thread_plan_sp->StopOthers();
205+
return false;
206+
}
207+
208+
void SBThreadPlan::SetStopOthers(bool stop_others) {
209+
LLDB_RECORD_METHOD(void, SBThreadPlan, SetStopOthers, (bool), stop_others);
210+
211+
ThreadPlanSP thread_plan_sp(GetSP());
212+
if (thread_plan_sp)
213+
thread_plan_sp->SetStopOthers(stop_others);
214+
}
215+
199216
// This section allows an SBThreadPlan to push another of the common types of
200217
// plans...
201218
//
@@ -463,6 +480,8 @@ void RegisterMethods<SBThreadPlan>(Registry &R) {
463480
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanComplete, ());
464481
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsPlanStale, ());
465482
LLDB_REGISTER_METHOD(bool, SBThreadPlan, IsValid, ());
483+
LLDB_REGISTER_METHOD(void, SBThreadPlan, SetStopOthers, (bool));
484+
LLDB_REGISTER_METHOD(bool, SBThreadPlan, GetStopOthers, ());
466485
LLDB_REGISTER_METHOD(lldb::SBThreadPlan, SBThreadPlan,
467486
QueueThreadPlanForStepOverRange,
468487
(lldb::SBAddress &, lldb::addr_t));

lldb/source/Commands/CommandObjectThread.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,16 @@ class ThreadStepScopeOptionGroup : public OptionGroup {
482482
// Check if we are in Non-Stop mode
483483
TargetSP target_sp =
484484
execution_context ? execution_context->GetTargetSP() : TargetSP();
485-
if (target_sp && target_sp->GetNonStopModeEnabled())
485+
if (target_sp && target_sp->GetNonStopModeEnabled()) {
486+
// NonStopMode runs all threads by definition, so when it is on we don't
487+
// need to check the process setting for runs all threads.
486488
m_run_mode = eOnlyThisThread;
489+
} else {
490+
ProcessSP process_sp =
491+
execution_context ? execution_context->GetProcessSP() : ProcessSP();
492+
if (process_sp && process_sp->GetSteppingRunsAllThreads())
493+
m_run_mode = eAllThreads;
494+
}
487495

488496
m_avoid_regexp.clear();
489497
m_step_in_target.clear();
@@ -612,8 +620,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
612620
if (m_options.m_run_mode == eAllThreads)
613621
bool_stop_other_threads = false;
614622
else if (m_options.m_run_mode == eOnlyDuringStepping)
615-
bool_stop_other_threads =
616-
(m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted);
623+
bool_stop_other_threads = (m_step_type != eStepTypeOut);
617624
else
618625
bool_stop_other_threads = true;
619626

lldb/source/Target/Process.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,12 @@ std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
278278
return std::chrono::seconds(value);
279279
}
280280

281+
bool ProcessProperties::GetSteppingRunsAllThreads() const {
282+
const uint32_t idx = ePropertySteppingRunsAllThreads;
283+
return m_collection_sp->GetPropertyAtIndexAsBoolean(
284+
nullptr, idx, g_process_properties[idx].default_uint_value != 0);
285+
}
286+
281287
bool ProcessProperties::GetOSPluginReportsAllThreads() const {
282288
const bool fail_value = true;
283289
const Property *exp_property =

lldb/source/Target/TargetProperties.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ let Definition = "process" in {
217217
def UtilityExpressionTimeout: Property<"utility-expression-timeout", "UInt64">,
218218
DefaultUnsignedValue<15>,
219219
Desc<"The time in seconds to wait for LLDB-internal utility expressions.">;
220+
def SteppingRunsAllThreads: Property<"run-all-threads", "Boolean">,
221+
DefaultFalse,
222+
Desc<"If true, stepping operations will run all threads. This is equivalent to setting the run-mode option to 'all-threads'.">;
220223
}
221224

222225
let Definition = "platform" in {

lldb/source/Target/Thread.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,7 +1380,7 @@ lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
13801380

13811381
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name,
13821382
extra_args_impl));
1383-
1383+
thread_plan_sp->SetStopOthers(stop_other_threads);
13841384
status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
13851385
return thread_plan_sp;
13861386
}

lldb/source/Target/ThreadPlanPython.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ using namespace lldb_private;
2525

2626
// ThreadPlanPython
2727

28-
ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
28+
ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name,
2929
StructuredDataImpl *args_data)
3030
: ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
3131
eVoteNoOpinion, eVoteNoOpinion),
32-
m_class_name(class_name), m_args_data(args_data), m_did_push(false) {
32+
m_class_name(class_name), m_args_data(args_data), m_did_push(false),
33+
m_stop_others(false) {
3334
SetIsMasterPlan(true);
3435
SetOkayToDiscard(true);
3536
SetPrivate(false);
@@ -162,13 +163,6 @@ lldb::StateType ThreadPlanPython::GetPlanRunState() {
162163
}
163164

164165
// The ones below are not currently exported to Python.
165-
166-
bool ThreadPlanPython::StopOthers() {
167-
// For now Python plans run all threads, but we should add some controls for
168-
// this.
169-
return false;
170-
}
171-
172166
void ThreadPlanPython::GetDescription(Stream *s, lldb::DescriptionLevel level) {
173167
s->Printf("Python thread plan implemented by class %s.",
174168
m_class_name.c_str());

lldb/test/API/functionalities/step_scripted/Steps.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,29 @@ def should_stop(self, event):
7575
if not self.value.IsValid():
7676
return True
7777

78-
print("Got next value: %d"%(self.value.GetValueAsUnsigned()))
7978
if not self.value.GetValueDidChange():
8079
self.child_thread_plan = self.queue_child_thread_plan()
8180
return False
8281
else:
8382
return True
83+
84+
# This plan does nothing, but sets stop_mode to the
85+
# value of GetStopOthers for this plan.
86+
class StepReportsStopOthers():
87+
stop_mode_dict = {}
88+
89+
def __init__(self, thread_plan, args_data, dict):
90+
self.thread_plan = thread_plan
91+
self.key = args_data.GetValueForKey("token").GetStringValue(1000)
92+
93+
def should_stop(self, event):
94+
self.thread_plan.SetPlanComplete(True)
95+
print("Called in should_stop")
96+
StepReportsStopOthers.stop_mode_dict[self.key] = self.thread_plan.GetStopOthers()
97+
return True
98+
99+
def should_step(self):
100+
return True
101+
102+
def explains_stop(self, event):
103+
return True

lldb/test/API/functionalities/step_scripted/TestStepScripted.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
Tests stepping with scripted thread plans.
33
"""
4-
4+
import threading
55
import lldb
66
import lldbsuite.test.lldbutil as lldbutil
77
from lldbsuite.test.decorators import *
@@ -108,3 +108,58 @@ def do_test_checking_variable(self, use_cli):
108108

109109
# And foo should have changed:
110110
self.assertTrue(foo_val.GetValueDidChange(), "Foo changed")
111+
112+
def test_stop_others_from_command(self):
113+
"""Test that the stop-others flag is set correctly by the command line.
114+
Also test that the run-all-threads property overrides this."""
115+
self.do_test_stop_others()
116+
117+
def run_step(self, stop_others_value, run_mode, token):
118+
import Steps
119+
interp = self.dbg.GetCommandInterpreter()
120+
result = lldb.SBCommandReturnObject()
121+
122+
cmd = "thread step-scripted -C Steps.StepReportsStopOthers -k token -v %s"%(token)
123+
if run_mode != None:
124+
cmd = cmd + " --run-mode %s"%(run_mode)
125+
print(cmd)
126+
interp.HandleCommand(cmd, result)
127+
self.assertTrue(result.Succeeded(), "Step scripted failed: %s."%(result.GetError()))
128+
print(Steps.StepReportsStopOthers.stop_mode_dict)
129+
value = Steps.StepReportsStopOthers.stop_mode_dict[token]
130+
self.assertEqual(value, stop_others_value, "Stop others has the correct value.")
131+
132+
def do_test_stop_others(self):
133+
self.build()
134+
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
135+
"Set a breakpoint here",
136+
self.main_source_file)
137+
# First run with stop others false and see that we got that.
138+
thread_id = ""
139+
if sys.version_info.major == 2:
140+
thread_id = str(threading._get_ident())
141+
else:
142+
thread_id = str(threading.get_ident())
143+
144+
# all-threads should set stop others to False.
145+
self.run_step(False, "all-threads", thread_id)
146+
147+
# this-thread should set stop others to True
148+
self.run_step(True, "this-thread", thread_id)
149+
150+
# The default value should be stop others:
151+
self.run_step(True, None, thread_id)
152+
153+
# The target.process.run-all-threads should override this:
154+
interp = self.dbg.GetCommandInterpreter()
155+
result = lldb.SBCommandReturnObject()
156+
157+
interp.HandleCommand("settings set target.process.run-all-threads true", result)
158+
self.assertTrue(result.Succeeded, "setting run-all-threads works.")
159+
160+
self.run_step(False, None, thread_id)
161+
162+
163+
164+
165+

0 commit comments

Comments
 (0)