This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Avoid moving ThreadPlanSP from plans vector
ClosedPublic

Authored by kastiglione on Jul 16 2021, 11:18 AM.

Details

Summary

Change ThreadPlanStack::PopPlan and ::DiscardPlan to not do the following:

  1. Move the last plan, leaving a moved ThreadPlanSP in the plans vector
  2. Call out to WillPop which can't guarantee that m_plans isn't accessed in its invalid state
  3. Pop the last plan off the plans vector

This leaves a period of time where the last element in the plans vector has been moved, leaving a null ThreadPlanSP in the container. There are asserts in place to prevent null ThreadPlanSP instances from being pushed on to the stack, and so this could break that invariant.

From discussion, it seems the use of std::move wasn't the result of a measured performance problem.

Diff Detail

Event Timeline

kastiglione requested review of this revision.Jul 16 2021, 11:18 AM
kastiglione created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJul 16 2021, 11:18 AM

Also call pop_back just after retrieving back.

aprantl added inline comments.Jul 16 2021, 6:37 PM
lldb/source/Target/ThreadPlanStack.cpp
152–153

Should we comment that we are intentionally making a copy of the SP to avoid a race condition with std::move()?

153

It's counterintuitive that WillPop() is being called *after* the value is popped now.

Rename WillPop to DidPop, and comment on m_plans invariant.

@aprantl I renamed WillPop to accurately reflect that it's DidPop. I also added a comment about the invariant that is broken when std::move is used on elements of m_plans.

Re-simplify following discussion with Adrian and Jim.

kastiglione marked 2 inline comments as done.Jul 27 2021, 4:49 PM
kastiglione edited the summary of this revision. (Show Details)Jul 27 2021, 4:53 PM
kastiglione edited the summary of this revision. (Show Details)
JDevlieghere accepted this revision.Jul 28 2021, 9:48 AM

IIRC the fact that the shared pointer is null is implementation defined and the standard just says that a moved-from object is in an undefined state.

lldb/source/Target/ThreadPlanStack.cpp
152–153

Note that moving the top element of the vector leaves it in an undefined state, which breaks the thread plan stack guarantee that the last element is valid.

This revision is now accepted and ready to land.Jul 28 2021, 9:48 AM

IIRC the fact that the shared pointer is null is implementation defined and the standard just says that a moved-from object is in an undefined state.

According to cppreference, the move constructor says:

After the construction, *this contains a copy of the previous state of r, r is empty and its stored pointer is null.

  • Reword comment using Jonas's suggestion
  • Pop the last plan right away, and thus change from WillPop to DidPop
kastiglione marked an inline comment as done.Jul 29 2021, 2:14 PM
jingham accepted this revision.Jul 29 2021, 2:18 PM

LGTM

This revision was landed with ongoing or failed builds.Aug 1 2021, 11:43 AM
This revision was automatically updated to reflect the committed changes.