kastiglione created this revision.
kastiglione added reviewers: jingham, aprantl.
kastiglione requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
Adjust `ShouldAutoContinue` to be available to any thread plan previous to the
plan that
explains a stop, not limited to the parent to the plan that explains the stop.
Before this change, `Thread::ShouldStop` did the following:
1. find the plan that explains the stop
2. if it's not a master plan, continue processing previous (aka parent) plans
3. first, call `ShouldAutoContinue` on the immediate parent of the explaining
plan
4. then loop over previous plans, calling `ShouldStop` and `MischiefManaged`
Of note, the iteration in step 4 does not call `ShouldAutoContinue`, so again
only the
plan just prior to the explaining plan is given the opportunity to override
whether to
continue or stop.
This commit changes the loop call `ShouldAutoContinue`, giving each plan the
opportunity
to override `ShouldStop` of previous plans.
Why? This allows a plan to do the following:
1. mark itself done and be popped off the stack
2. allow parent plans to finish their work, and to also be popped off the stack
3. and finally, have the thread continue, not stop
This is useful for stepping into async functions. A plan will would step far
enough
enough to set a breakpoint on the async target, and then use
`ShouldAutoContinue` to
unwind the necessary stepping, and then have the calling thread continue.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D97076
Files:
lldb/include/lldb/Target/ThreadPlan.h
lldb/source/Target/Thread.cpp
Index: lldb/source/Target/Thread.cpp
===================================================================
--- lldb/source/Target/Thread.cpp
+++ lldb/source/Target/Thread.cpp
@@ -829,6 +829,8 @@
ThreadPlan *plan_ptr = current_plan;
while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
if (plan_ptr->PlanExplainsStop(event_ptr)) {
+ LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());
+
should_stop = plan_ptr->ShouldStop(event_ptr);
// plan_ptr explains the stop, next check whether plan_ptr is done,
@@ -858,10 +860,7 @@
}
if (!done_processing_current_plan) {
- bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
-
- LLDB_LOGF(log, "Plan %s explains stop, auto-continue %i.",
- current_plan->GetName(), over_ride_stop);
+ bool override_stop = false;
// We're starting from the base plan, so just let it decide;
if (current_plan->IsBasePlan()) {
@@ -882,19 +881,24 @@
if (should_stop)
current_plan->WillStop();
+ PopPlan();
+
+ if (current_plan->ShouldAutoContinue(event_ptr)) {
+ override_stop = true;
+ LLDB_LOGF(log, "Plan %s auto-continue: true.",
+ current_plan->GetName());
+ }
+
// If a Master Plan wants to stop, we let it. Otherwise, see if the
// plan's parent wants to stop.
if (should_stop && current_plan->IsMasterPlan()) {
- PopPlan();
break;
- } else {
- PopPlan();
+ }
- current_plan = GetCurrentPlan();
- if (current_plan == nullptr) {
- break;
- }
+ current_plan = GetCurrentPlan();
+ if (current_plan == nullptr) {
+ break;
}
} else {
break;
@@ -902,7 +906,7 @@
}
}
- if (over_ride_stop)
+ if (override_stop)
should_stop = false;
}
Index: lldb/include/lldb/Target/ThreadPlan.h
===================================================================
--- lldb/include/lldb/Target/ThreadPlan.h
+++ lldb/include/lldb/Target/ThreadPlan.h
@@ -351,6 +351,12 @@
virtual bool ShouldStop(Event *event_ptr) = 0;
+ /// Returns whether this thread plan overrides the `ShouldStop` of previous
+ /// plans.
+ ///
+ /// When processing the thread plan stack, this function gives plans the
+ /// ability to continue - even when previous plans subsequently return false
+ /// from `ShouldStop`. \see Thread::ShouldStop
virtual bool ShouldAutoContinue(Event *event_ptr) { return false; }
// Whether a "stop class" event should be reported to the "outside world".
Index: lldb/source/Target/Thread.cpp
===================================================================
--- lldb/source/Target/Thread.cpp
+++ lldb/source/Target/Thread.cpp
@@ -829,6 +829,8 @@
ThreadPlan *plan_ptr = current_plan;
while ((plan_ptr = GetPreviousPlan(plan_ptr)) != nullptr) {
if (plan_ptr->PlanExplainsStop(event_ptr)) {
+ LLDB_LOGF(log, "Plan %s explains stop.", plan_ptr->GetName());
+
should_stop = plan_ptr->ShouldStop(event_ptr);
// plan_ptr explains the stop, next check whether plan_ptr is done,
@@ -858,10 +860,7 @@
}
if (!done_processing_current_plan) {
- bool over_ride_stop = current_plan->ShouldAutoContinue(event_ptr);
-
- LLDB_LOGF(log, "Plan %s explains stop, auto-continue %i.",
- current_plan->GetName(), over_ride_stop);
+ bool override_stop = false;
// We're starting from the base plan, so just let it decide;
if (current_plan->IsBasePlan()) {
@@ -882,19 +881,24 @@
if (should_stop)
current_plan->WillStop();
+ PopPlan();
+
+ if (current_plan->ShouldAutoContinue(event_ptr)) {
+ override_stop = true;
+ LLDB_LOGF(log, "Plan %s auto-continue: true.",
+ current_plan->GetName());
+ }
+
// If a Master Plan wants to stop, we let it. Otherwise, see if the
// plan's parent wants to stop.
if (should_stop && current_plan->IsMasterPlan()) {
- PopPlan();
break;
- } else {
- PopPlan();
+ }
- current_plan = GetCurrentPlan();
- if (current_plan == nullptr) {
- break;
- }
+ current_plan = GetCurrentPlan();
+ if (current_plan == nullptr) {
+ break;
}
} else {
break;
@@ -902,7 +906,7 @@
}
}
- if (over_ride_stop)
+ if (override_stop)
should_stop = false;
}
Index: lldb/include/lldb/Target/ThreadPlan.h
===================================================================
--- lldb/include/lldb/Target/ThreadPlan.h
+++ lldb/include/lldb/Target/ThreadPlan.h
@@ -351,6 +351,12 @@
virtual bool ShouldStop(Event *event_ptr) = 0;
+ /// Returns whether this thread plan overrides the `ShouldStop` of previous
+ /// plans.
+ ///
+ /// When processing the thread plan stack, this function gives plans the
+ /// ability to continue - even when previous plans subsequently return false
+ /// from `ShouldStop`. \see Thread::ShouldStop
virtual bool ShouldAutoContinue(Event *event_ptr) { return false; }
// Whether a "stop class" event should be reported to the "outside world".
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits