[lldb-dev] Process plugin implementation with multiple threads

jingham at apple.com jingham at apple.com
Mon Dec 1 11:01:14 PST 2014


> On Nov 24, 2014, at 3:20 PM, Zachary Turner <zturner at google.com> wrote:
> 
> 
> 
> On Fri Nov 14 2014 at 4:13:17 PM <jingham at apple.com> wrote:
> 
> > 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"...
> 
> 
> 
> Digging up this old thread a little bit.  So on Windows now I can launch a process with -s to stop at the initial breakpoint, and when I do this I can print register values, stack frames, and lots of other things.
> 
> But RefreshStateAfterStop isn't being called for the initial stop.  This is where I've put all my code to update the StopInfo of the various threads, so currently for the initial breakpoint I've got no way to tell the threads why they're stopped.
> 
> There's a comment in Process::Launch() that seems to justify this, which says this:
> 
> // Note, the stop event was consumed above, but not handled. This was done
> // to give DidLaunch a chance to run. The target is either stopped or crashed.
> // Directly set the state.  This is done to prevent a stop message with a bunch
> // of spurious output on thread status, as well as not pop a ProcessIOHandler.
> 
> But still, this is a real stop that will cause the debugger to break.  Is it a bug that RefreshStateAfterStop isn't being called for this?


Sounds like it to me.  You don't want to call RefreshStateAfterStop if you don't need to (for instance if processing this first stop when you're just going to auto-continue or any other "synchronous" breakpoint callback like the shared library load notification) since it could be a little expensive.  But if you are ever going to return control to the user you need to call RefreshStateAfterStop.

Jim






More information about the lldb-dev mailing list