[lldb-dev] Continuing from a breakpoint with multiple threads

Adrian McCarthy amccarth at google.com
Mon Jun 1 13:26:41 PDT 2015


I think Zach's right.  The only plugin that calls SetResumeState inside
WillResume is POSIXThread, and that seems to be overridden by FreeBSDThread.

If I remove the call of SetResumeState from
TargetThreadWindows::WillResume, everything starts to work.

I'll look into adding some logging in ThreadList::WillResume.

Thanks everyone.

On Mon, Jun 1, 2015 at 12:58 PM, Zachary Turner <zturner at google.com> wrote:

> Currently ThreadWindows::WillResume() looks like this:
>
>
> void
> TargetThreadWindows::WillResume(lldb::StateType resume_state)
> {
>     SetResumeState(resume_state);
> }
>
> I originally put this code in because that's what one or two of the other
> plugins did and I wasn't sure what the "correct" thing to do was.  I'm not
> sure if it's correct though, or if it could be a cause for the bug.  But if
> the resume state is eStateSuspended as you say, then that suggests that
> something lower level already decided that this thread should continue to
> be suspended after the user continues.  So the bug might actually still be
> earlier.
>
> There's not a lot of logging in ThreadList::WillResume, I wonder if it
> would be worth adding some?
>
> On Mon, Jun 1, 2015 at 12:44 PM Adrian McCarthy <amccarth at google.com>
> wrote:
>
>> >The way this works is that when we go to resume the process, all the
>> thread's get asked whether they need to stop other threads to implement
>> whatever strategy they are currently pursuing.  That query ends up calling
>> the currently active thread plan's "StopOthers" method.
>>
>> Right, and since the ThreadPlanStepOverBreakpoint responds true to
>> StopOthers, all the other threads get suspended.  Once the breakpoint is
>> restored and stepped over and the ThreadPlanStepOverBreakpoint is popped,
>> the rest of the threads are still suspended.
>>
>> > But ThreadPlanBase::ShouldStop returns false, so if all your threads
>> are running just the ThreadPlanBase, then they should all resume.
>>
>> Except that ShouldStop is not called for threads that are already
>> suspended  (Thread::ShouldStop has an early out if the resume state is
>> eStateSuspended).  So I still don't see how those threads can ever get out
>> of the suspended state.
>>
>>
>>
>> On Mon, Jun 1, 2015 at 11:51 AM, Jim Ingham <jingham at apple.com> wrote:
>>
>>> The way this works is that when we go to resume the process, all the
>>> thread's get asked whether they need to stop other threads to implement
>>> whatever strategy they are currently pursuing.  That query ends up calling
>>> the currently active thread plan's "StopOthers" method.  If one thread
>>> returns true to StopOthers, then that thread will get to run solo.  If more
>>> than one thread returns true I do a little round robin to pick which one
>>> gets to go.  But ThreadPlanBase::ShouldStop returns false, so if all your
>>> threads are running just the ThreadPlanBase, then they should all resume.
>>>
>>> This all happens in ThreadList::WillResume.
>>>
>>> Note I started to add some commands to manipulate the thread plans - of
>>> which "thread plan list" is the relevant one.  The work isn't done yet (for
>>> instance I should actually DO something with the --internal and --verbose
>>> options, but for now I only print user visible plans, not implementation
>>> only plans.  Anyway, if you are poking around in this area that might be of
>>> some use.
>>>
>>> Jim
>>>
>>>
>>> > On Jun 1, 2015, at 8:04 AM, Adrian McCarthy <amccarth at google.com>
>>> wrote:
>>> >
>>> > Thanks for the info.
>>> >
>>> > This is not theoretical.  I'm trying to get TestBreakAfterJoin to pass
>>> on Windows.  Step 1 was to convert it use <thread> instead of
>>> <pthreads.h>.  Step 2 was to fix some minor issues in TargetThreadWindows.
>>> >
>>> > But now the inferior deadlocks because the one thread that's not
>>> suspended is waiting on the ones that are.  Once the
>>> ThreadPlanStepOverBreakpoint plan is popped, the current plan is
>>> ThreadPlanBase, which, as far as I can tell, does nothing to resume
>>> suspended threads.
>>> >
>>> > I'll compare this to what happens on another platform to see if there
>>> should be some other thread plan in use.
>>> >
>>> > Adrian.
>>> >
>>> > On Fri, May 29, 2015 at 4:50 PM, Jim Ingham <jingham at apple.com> wrote:
>>> > When stepping over a breakpoint, the ThreadPlanStepOverBreakpoint gets
>>> pushed, handles the single instruction step - during which it does suspend
>>> the other threads - then it gets popped.  When you next resume, whatever
>>> plan was handling the stepping before the breakpoint was hit will resume
>>> with whatever policy for running other threads it was using.
>>> >
>>> > So it's up to the plan that was on the stack before the
>>> "StepOverBreakpoint" was pushed to decide this.  Most of the more complex
>>> plans (like step-over/step-into) try to keep the other threads from running
>>> if possible (unless the user instructed otherwise) but they also will let
>>> all the threads run if there's something going on that might deadlock.  For
>>> instance, if you are doing "next" and we step through straight-line
>>> instructions in a function, we will only run the one thread you are
>>> stepping in (by default, you can control this with options to the "thread
>>> step-over" command.   But if we step into a function, we set a breakpoint
>>> on the return address and then run with all threads resumed because
>>> stepping out of a function could run arbitrary code.
>>> >
>>> > Anyway, was this a theoretical question, or do you have some instance
>>> where you are actually seeing a deadlock?
>>> >
>>> > Jim
>>> >
>>> >
>>> > > On May 29, 2015, at 1:59 PM, Adrian McCarthy <amccarth at google.com>
>>> wrote:
>>> > >
>>> > > [I'm trying to make TestBreakAfterJoin work on Windows.]
>>> > >
>>> > > I'm unclear how continuing from a breakpoint in a multi-threaded
>>> inferior is supposed to work.
>>> > >
>>> > > A breakpoint is set, and the inferior runs until one of its threads
>>> hits the breakpoint.  The user then selects continue.
>>> > >
>>> > > The thread that had hit the breakpoint has a thread plan type of
>>> ThreadPlanStepOverBreakpoint, which causes all of the other threads to be
>>> set to state eStateSuspended.  The thread that had hit the breakpoint then
>>> steps beyond the breakpoint, and the breakpoint is restored.  The thread is
>>> then resumed again.
>>> > >
>>> > > But the other threads are all still suspended, causing the inferior
>>> to deadlock.
>>> > >
>>> > > The question is:  Where should the other threads have their resume
>>> states set back to a running state?
>>> > >
>>> > > Adrian
>>> > > _______________________________________________
>>> > > lldb-dev mailing list
>>> > > lldb-dev at cs.uiuc.edu
>>> > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>>> >
>>> >
>>>
>>>
>> _______________________________________________
>> lldb-dev mailing list
>> lldb-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150601/731028e5/attachment.html>


More information about the lldb-dev mailing list