[lldb-dev] Process plugin implementation with multiple threads

jingham at apple.com jingham at apple.com
Fri Nov 14 16:13:14 PST 2014


> On Nov 14, 2014, at 3:46 PM, Zachary Turner <zturner at google.com> wrote:
> 
> It's possible, but Windows gives us a handle to the thread which has all privileges associated with it (in other words we can use it for just about anything), so it's considered better to use the handle windows gives us. At the very least we'd want to queue up all the incoming event notifications that we get from this loop, and then use it to update the state when someone stops.

You get one view of the thread if you catch the event but another if you enumerate them when stopped?  That's awkward.

> 
> Just to be certain, when you and Greg refer to "when someone has stopped", I assume you are referring to a public stop, i.e. someone has to enter a command to resume the debugger?
> 
> I was wondering why my RefreshStateAfterStop override was never being called, I'm guessing now that it's because I was only updating the private state, and this only gets called on a public stop.
> 
> 

That's not quite what happens, I don't know if what actually happens also explains what you are seeing, but this is how this bit of logic works:  

When the private state gets changed we generate an event and put it on the public event queue.  Then we call "Process::ShouldBroadcastEvent", to decide whether to deliver the event to the listener on the process broadcaster. RefreshStateAfterStop gets called in ShouldBroadcastEvent, just before we go into the decision loop about whether to broadcast a stopped event or not.  The event might not be broadcast, for instance it might get consumed by the thread plans because the stop was just one part of their larger designs.  If we do decide to broadcast the event, it gets put on the event queue.  Then when the event gets consumed by the process listener THAT'S when the public state finally gets updated.  Note, even if we broadcast an event we might not change the state, since one of the StopInfo actions might have restarted the process (e.g. a breakpoint command).  In that case we don't change the public state, but just mark the event as a stopped event with the restarted flag set.

This little dance is kind of obnoxious, but it is required so that the thread plans can do their jobs without spamming the public event consumer with all sorts of spurious stops and starts, and also so that the state is kept in sync with the last event you've consumed.  After all, if your process ran and stopped again right away, and you had consumed the "running" event, but hadn't consumed the "stopped" event, it would be kind of disconcerting for the state to be "stopped"...

Hope that helps.

Jim
 

> On Fri Nov 14 2014 at 3:26:47 PM <jingham at apple.com> wrote:
> Is there a way to ask Windows "give me all the threads for this process"?  If so, the path of least resistance would be to ignore the Thread Created events in this loop, and then only generate the thread list on demand when someone has stopped.
> 
> At some point we'll want to do keep alive debugging and then we'll have to handle posting interesting events while the process is still running.  But I don't want to do that piecemeal.
> 
> For now, putting threads in the thread list while the debugger is running from both the private & public state's perspective does no good, and putting them in between a stop & an immediate continue doesn't do anybody any good either.  You're just making your plugin more fragile.
> 
> Jim
> 
> 
> > On Nov 14, 2014, at 3:08 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > The way Windows debug notifications work is like this:
> >
> > while (WaitForDebugEvent(&event))   // Block until something happens in the process
> > {
> >    // Windows stopped the process for us automatically.  Do something with the event
> >
> >    ContinueDebugEvent(&event);  // Resume the process
> > }
> >
> > After WaitForDebugEvent and before I call ContinueDebugEvent, the event might say that a new thread was created.  So at this point I'd like to update the thread list.  The process is actually stopped here, but it shouldn't appear so to the user. So at the beginning I tell LLDB the process is stopped -- SetPrivateState(eStateStopped), and at the end I tell it that it's running again -- SetPrivateState(eStateRunning).
> >
> > However, this code is still running on a different from what LLDB is going to invoke methods on the plugin.  RefreshStateAfterStop, DoResume, etc are all going to be running on a different thread from this loop.  The code is simpler if I can just stick the new thread in the ThreadList (or whatever other state needs updating if it's not thread related) right here from this thread.  Alternatively, when I set the state to eStateStopped presumably that will trigger LLDB to call RefreshStateAfterStop() from the other thread.  I can also modify the state then, it just requiers a little extra work as I have to do some synchronization and marshalling / storage of the event parameters.
> >
> > On Fri Nov 14 2014 at 2:53:35 PM Greg Clayton <gclayton at apple.com> wrote:
> >
> > > On Nov 14, 2014, at 10:15 AM, Zachary Turner <zturner at google.com> wrote:
> > >
> > > Windows doesn't need to do anything special for each thread as it is created. Only need to update the thread list in the Process object as far as we're concerned, but that's it.
> > >
> > > The main thing I'm worried about is that the Process object itself runs a couple of threads in the background (the private state thread, for example), so I was worried about possible race conditions when modifying state asynchronously (i.e. from my debugger thread).
> >
> > What state needs to be updated asynchronously? You shouldn't be touching the thread list (no need to update it, you should be able to update it on demand each time you actually stop right?) at all until you have a valid stop reason and then the process will update the threads itself when and if it needs them.
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev





More information about the lldb-dev mailing list