<div dir="ltr"><div>Hello, </div><div><br></div><div>Look at it: <a href="http://reviews.llvm.org/D8541">http://reviews.llvm.org/D8541</a></div><div>Perhaps it will fix your test cases too.</div><div><br></div><div>Thanks,</div><div>Ilia</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 23, 2015 at 5:58 PM, Ted Woodward <span dir="ltr"><<a href="mailto:ted.woodward@codeaurora.org" target="_blank">ted.woodward@codeaurora.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">We've seen the same behavior when running an lldb command file at startup.<br>
<br>
Foo contains:<br>
b main<br>
run<br>
<br>
lldb -s foo test.exe<br>
(this hangs)<br>
<br>
Take out the run from foo, and<br>
lldb -s foo -o run test.exe<br>
(this works)<br>
<br>
--<br>
Qualcomm Innovation Center, Inc.<br>
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a<br>
Linux Foundation Collaborative Project<br>
<div class="HOEnZb"><div class="h5"><br>
> -----Original Message-----<br>
> From: <a href="mailto:lldb-dev-bounces@cs.uiuc.edu">lldb-dev-bounces@cs.uiuc.edu</a> [mailto:<a href="mailto:lldb-dev-bounces@cs.uiuc.edu">lldb-dev-bounces@cs.uiuc.edu</a>]<br>
On<br>
> Behalf Of Pavel Labath<br>
> Sent: Monday, March 23, 2015 4:22 AM<br>
> To: Zachary Turner<br>
> Cc: <a href="mailto:lldb-dev@cs.uiuc.edu">lldb-dev@cs.uiuc.edu</a><br>
> Subject: Re: [lldb-dev] Synchronous execution with process plugin<br>
><br>
> This looks very much like the issue I was experiencing on linux, where<br>
lldb<br>
> would just lock up if I executed the process in synchronous mode.<br>
> This was fixed with <<a href="http://reviews.llvm.org/D8079" target="_blank">http://reviews.llvm.org/D8079</a>>, and I suspect you<br>
need to<br>
> do something similar. The trick here is that you need to set up process<br>
event<br>
> hijacking in your host launch code. Otherwise, Target::Launch will attempt<br>
to<br>
> use the global process listener to wait for the process to stop. However,<br>
this will<br>
> race with the event handler thread, since it uses the same listener to<br>
process<br>
> events. So, depending on which thread processes the event, it will either<br>
work<br>
> fine, or you will end up locked in WaitForProcessToStop forever, because<br>
the<br>
> event will never come.<br>
><br>
> Also, note that there is another issue with launching in synchronous mode,<br>
> where stdio is not forwarded to the target process<br>
> <<a href="http://lists.cs.uiuc.edu/pipermail/lldb-dev/2015-March/006853.html" target="_blank">http://lists.cs.uiuc.edu/pipermail/lldb-dev/2015-March/006853.html</a>>.<br>
> I was planning on dealing with this, but I don't think I will get around<br>
to it for a<br>
> while yet...<br>
><br>
> pl<br>
><br>
> On 21 March 2015 at 01:35, Zachary Turner <<a href="mailto:zturner@google.com">zturner@google.com</a>> wrote:<br>
> > Hmm, on Monday I'll try to see if i can figure out where to put a<br>
> > breakpoint to get hit when someone removes something from the queue.<br>
> > Thanks On Fri, Mar 20, 2015 at 5:52 PM <<a href="mailto:jingham@apple.com">jingham@apple.com</a>> wrote:<br>
> >><br>
> >><br>
> >> > On Mar 20, 2015, at 5:21 PM, Zachary Turner <<a href="mailto:zturner@google.com">zturner@google.com</a>><br>
> wrote:<br>
> >> ><br>
> >> > If I do that my process does stop at main, but I think I'm hit with<br>
> >> > a race condition. 3 times out of 5 I saw the same results as you,<br>
> >> > where it doesn't print the backtrace but if I do bt it works fine.<br>
> >> > The other 2 times out of 5 It does print the backtrace, but then<br>
> >> > I'm deadlocked. I added a bunch of tracepoints so we can see the<br>
> >> > order of events. here's what it looks like when it deadlocks.<br>
> >> ><br>
> >> > Target::Launch about to call ProcessWindows::Launch<br>
> >> > ProcessWindows::DoLaunch entering ProcessWindows::DoLaunch about to<br>
> >> > call DebugLaunch ProcessWindows::DoLaunch succeeded, waiting for<br>
> >> > initial stop Application<br>
> >> > "\??\D:\src\llvm\tools\lldb\test\expression_command\formatters\a.ou<br>
> >> > t" found in cache ProcessWindows::OnDebuggerConnected<br>
> >> > ProcessWindows::OnDebugException<br>
> >> > ProcessWindows got EXCEPTION_BREAKPOINT ProcessWindows got initial<br>
> >> > stop, setting initial stop event ProcessWindows::DoLaunch received<br>
> >> > initial stop, returning ProcessWindows::DoLaunch finished launching<br>
> >> > process, exiting Target::Launch returned from<br>
> >> > ProcessWindows::DoLaunch, eLaunchFlagStopAtEntry == false, about to<br>
> >> > call WaitForProcessToStop Target::Launch, WaitForProcessToStop<br>
> >> > returned, new state = eStateStopped Target::Launch about to call<br>
> >> > ProcessWindows::PrivateResume ProcessWindows::DoResume resuming<br>
> >> > from active exception ProcessWindows::DoResume couldn't find an<br>
> >> > active exception, setting state to eStateRunning<br>
> >> > ProcessWindows::OnDebugException ProcessWindows got<br>
> >> > EXCEPTION_BREAKPOINT Target::Launch synchronous_execution is true,<br>
> >> > calling WaitForProcessToStop again<br>
> >> ><br>
> >> > The interesting stuff is the last 2 lines. It hits the breakpoint<br>
> >> > in main *before* calling WaitForProcessToStop, so<br>
> >> > WaitForProcessToStop never sees a "change".<br>
> >><br>
> >> > Here's what it looks like when it works.<br>
> >> ><br>
> >> > Target::Launch about to call ProcessWindows::Launch<br>
> >> > ProcessWindows::DoLaunch entering ProcessWindows::DoLaunch about to<br>
> >> > call DebugLaunch ProcessWindows::DoLaunch succeeded, waiting for<br>
> >> > initial stop Application<br>
> >> > "\??\D:\src\llvm\tools\lldb\test\expression_command\formatters\a.ou<br>
> >> > t" found in cache ProcessWindows::OnDebuggerConnected<br>
> >> > ProcessWindows::OnDebugException<br>
> >> > ProcessWindows got EXCEPTION_BREAKPOINT ProcessWindows got initial<br>
> >> > stop, setting initial stop event ProcessWindows::DoLaunch received<br>
> >> > initial stop, returning ProcessWindows::DoLaunch finished launching<br>
> >> > process, exiting ProcessWindows breakpoint handler set private<br>
> >> > state to eStateStopped Target::Launch returned from<br>
> >> > ProcessWindows::DoLaunch, eLaunchFlagStopAtEntry == false, about to<br>
> >> > call WaitForProcessToStop Target::Launch, WaitForProcessToStop<br>
> >> > returned, new state = eStateStopped Target::Launch about to call<br>
> >> > ProcessWindows::PrivateResume ProcessWindows::DoResume resuming<br>
> >> > from active exception ProcessWindows::DoResume couldn't find an<br>
> >> > active exception, nothing to resume<br>
> >> > ProcessWindows::OnDebugException ProcessWindows got<br>
> >> > EXCEPTION_BREAKPOINT Target::Launch synchronous_execution is true,<br>
> >> > calling WaitForProcessToStop again ProcessWindows breakpoint<br>
> >> > handler set private state to eStateStopped Target::Launch<br>
> >> > WaitForProcessToStop returned, yay!<br>
> >> ><br>
> >> ><br>
> >> > The difference here is that "calling WaitForProcessToStop again"<br>
happens<br>
> >> > before the process plugin sets the private state. Can you try<br>
repeating<br>
> >> > your test multiple times and seeing if you can get the deadlock to<br>
occur?<br>
> >><br>
> >> I can't get this to fail on OS X but with timing related things I'm<br>
> >> not sure that's all that significant...<br>
> >><br>
> >> Anyway, what you are describing doesn't make sense to me yet. After<br>
> >> calling PrivateResume, we call WaitForProcessToStop, passing<br>
> "wait_always"<br>
> >> set to true. When wait_always is true, WaitForProcessToStop won't<br>
> >> return till it receives a stop event. It isn't comparing current<br>
> >> state against desired state, it is actually waiting for an event. So<br>
> >> it should not matter when the breakpoint hit arrives relative to<br>
calling<br>
> "WaitForProcessToStop"<br>
> >> since the breakpoint hit is just going to generate a stop event,<br>
> >> which will sit in the event queue till somebody fetches it. It's<br>
> >> fine for that to happen before you call WaitForProcessToStop, because<br>
> >> we aren't comparing current to desired state, we are waiting for that<br>
event.<br>
> >><br>
> >> Maybe somebody else is grabbing the breakpoint stop event and taking<br>
> >> it off of the queue? That would explain why the second<br>
> >> WaitForProcessToStop - the one with wait_always set to true - is<br>
missing the<br>
> event?<br>
> >><br>
> >> Jim<br>
> >><br>
> >><br>
> >> ><br>
> >> ><br>
> >> > On Fri, Mar 20, 2015 at 4:49 PM <<a href="mailto:jingham@apple.com">jingham@apple.com</a>> wrote:<br>
> >> > I'm not sure it is deadlocking the debugger. lldb is just waiting<br>
> >> > for a stop. For instance ^C should interrupt it, or sending a<br>
> >> > signal externally to the process, or triggering a breakpoint or<br>
crash, etc.<br>
> >> ><br>
> >> > Actually, Greg must have fixed the bug I was remembering, because<br>
> >> > this works correctly for me with TOT lldb.<br>
> >> ><br>
> >> > What happens for you if your .lldbinit has:<br>
> >> ><br>
> >> > file a.out<br>
> >> > break set -n main<br>
> >> > run<br>
> >> ><br>
> >> > For me this stops at the breakpoint at main. We still have a<br>
> >> > little clean up to do here, because I don't see the stop notification<br>
in this<br>
> case.<br>
> >> > I see:<br>
> >> ><br>
> >> > > lldb -S cmds.lldb<br>
> >> > (lldb) command source -s 1 'cmds.lldb'<br>
> >> > 4 locations added to breakpoint 1<br>
> >> > (lldb)<br>
> >> ><br>
> >> > but if I then do "bt" I'm sitting at main:<br>
> >> ><br>
> >> > (lldb) bt<br>
> >> > * thread #1: tid = 0x1bf8a4, function: main , stop reason =<br>
> >> > breakpoint<br>
> >> > 1.1<br>
> >> > * frame #0: 0x0000000100018e87 Sketch`main at SKTMain.m:17<br>
> >> > frame #1: 0x00007fff94f445ad libdyld.dylib`start<br>
> >> > frame #2: 0x00007fff94f445ad libdyld.dylib`start<br>
> >> ><br>
> >> > Not sure what's up with the stutter at start either. But that's a<br>
> >> > different rabbit to chase...<br>
> >> ><br>
> >> > Jim<br>
> >> ><br>
> >> ><br>
> >> > > On Mar 20, 2015, at 4:40 PM, Zachary Turner <<a href="mailto:zturner@google.com">zturner@google.com</a>><br>
> >> > > wrote:<br>
> >> > ><br>
> >> > > If that's the case, then a .lldbinit file like this:<br>
> >> > ><br>
> >> > > file a.out<br>
> >> > > run<br>
> >> > ><br>
> >> > > Will deadlock the debugger, because the real stop never comes?<br>
> >> > ><br>
> >> > > On Fri, Mar 20, 2015 at 4:35 PM <<a href="mailto:jingham@apple.com">jingham@apple.com</a>> wrote:<br>
> >> > > That's the stop at entry stop. The code you quoted is in a block<br>
> >> > > that starts with:<br>
> >> > ><br>
> >> > > if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry)<br>
> >> > > ==<br>
> >> > > false)<br>
> >> > > {<br>
> >> > ><br>
> >> > > So we've stopped at the entry point, but the user didn't want to<br>
> >> > > know about that, so we resume and wait for a "real" stop.<br>
> >> > ><br>
> >> > > Jim<br>
> >> > ><br>
> >> > ><br>
> >> > > > On Mar 20, 2015, at 4:30 PM, Zachary Turner<br>
> >> > > > <<a href="mailto:zturner@google.com">zturner@google.com</a>><br>
> >> > > > wrote:<br>
> >> > > ><br>
> >> > > > I'm a little confused. You said that in synchronous execution,<br>
> >> > > > Launch won't return until the process has stopped. That makes<br>
> >> > > > sense, but it already checks that the process has stopped once<br>
> >> > > > regardless of whether synchronous execution is set. Then, it<br>
> >> > > > calls PrivateResume() (even if synchronous_execution is set), and<br>
then<br>
> waits for the process to stop again?<br>
> >> > > > What would trigger this second stop? Target::Launch already<br>
> >> > > > asked it to resume, so now it's happily running while<br>
> >> > > > Target::Launch is waiting for it to stop a second time.<br>
> >> > > ><br>
> >> > > > On Fri, Mar 20, 2015 at 4:23 PM <<a href="mailto:jingham@apple.com">jingham@apple.com</a>> wrote:<br>
> >> > > > In synchronous execution, the "Launch" command won't return<br>
> >> > > > till the process has stopped. The point of synchronous execution<br>
is that<br>
> you can do:<br>
> >> > > ><br>
> >> > > > break set -n foo<br>
> >> > > > run<br>
> >> > > > bt<br>
> >> > > ><br>
> >> > > > So "run" can't return till the breakpoint has been hit. That<br>
> >> > > > is why it waits for the process to stop. I'm not quite sure<br>
> >> > > > why this is done in Target::Launch, in other cases (e.g. in for<br>
> >> > > > "step" and "continue" the command object is the one that takes<br>
> >> > > > care of waiting for the stop. Launch is a little funny<br>
> >> > > > however, because it can't use the normal process wait mechanism<br>
> >> > > > to do its job since the real process isn't alive when it has to<br>
start<br>
> waiting...<br>
> >> > > ><br>
> >> > > > I think the reason you are hanging here is that the code that<br>
> >> > > > reads in all the init statements runs an event loop temporarily<br>
> >> > > > while it is reading them in, and the kills that and hands off<br>
> >> > > > the the real command execution loop, and this continuation gets<br>
> >> > > > lost in the handoff. I thought Greg had already fixed that, but<br>
maybe<br>
> it's still sitting in his queue.<br>
> >> > > ><br>
> >> > > > Jim<br>
> >> > > ><br>
> >> > > ><br>
> >> > > ><br>
> >> > > ><br>
> >> > > > > On Mar 20, 2015, at 3:57 PM, Zachary Turner<br>
> >> > > > > <<a href="mailto:zturner@google.com">zturner@google.com</a>><br>
> >> > > > > wrote:<br>
> >> > > > ><br>
> >> > > > > I ran into an issue earlier where I tried to make a .lldbinit<br>
> >> > > > > file with some lines like this:<br>
> >> > > > ><br>
> >> > > > > file a.out<br>
> >> > > > > run<br>
> >> > > > ><br>
> >> > > > ><br>
> >> > > > > When this happens the process runs, the breakpoint gets hit<br>
> >> > > > > and I see the source listing, it returns to the lldb prompt,<br>
> >> > > > > but then I can't type anything. It appears LLDB is<br>
> >> > > > > deadlocked inside of Target::Launch() at the following<br>
location:<br>
> >> > > > ><br>
> >> > > > > if (!synchronous_execution)<br>
> >> > > > > m_process_sp->RestoreProcessEvents ();<br>
> >> > > > ><br>
> >> > > > > error = m_process_sp->PrivateResume();<br>
> >> > > > ><br>
> >> > > > > if (error.Success())<br>
> >> > > > > {<br>
> >> > > > > // there is a race condition where this<br>
> >> > > > > thread will return up the call stack to the main command<br>
> >> > > > > // handler and show an (lldb) prompt<br>
> >> > > > > before HandlePrivateEvent (from PrivateStateThread) has<br>
> >> > > > > // a chance to call PushProcessIOHandler()<br>
> >> > > > > m_process_sp->SyncIOHandler(2000);<br>
> >> > > > ><br>
> >> > > > > if (synchronous_execution)<br>
> >> > > > > {<br>
> >> > > > ><br>
> >> > > > > state = m_process_sp->WaitForProcessToStop (NULL, NULL, true,<br>
> >> > > > > hijack_listener_sp.get(), stream);<br>
> >> > > > > const bool must_be_alive = false; //<br>
> >> > > > > eStateExited is ok, so this must be false<br>
> >> > > > > if (!StateIsStoppedState(state,<br>
> >> > > > > must_be_alive))<br>
> >> > > > > {<br>
> >> > > > ><br>
> >> > > > > error.SetErrorStringWithFormat("process isn't stopped: %s",<br>
> >> > > > > StateAsCString(state));<br>
> >> > > > > }<br>
> >> > > > > }<br>
> >> > > > > }<br>
> >> > > > ><br>
> >> > > > > Normally when I'm using LLDB and entering the commands<br>
> >> > > > > myself, this synchronous_execution value is not set, and<br>
> >> > > > > everything works as expected. How is this supposed to work?<br>
> >> > > > > What does my plugin need to do differently in order to handle<br>
> >> > > > > this case? The process has already stopped once and resumed,<br>
> >> > > > > so I'm not sure why it would need to stop again? I see that<br>
> >> > > > > it's not restoring process events in the case of synchronous<br>
> execution, so maybe it should have never resumed in the first place?<br>
> >> > > > > _______________________________________________<br>
> >> > > > > lldb-dev mailing list<br>
> >> > > > > <a href="mailto:lldb-dev@cs.uiuc.edu">lldb-dev@cs.uiuc.edu</a><br>
> >> > > > > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev</a><br>
> >> > > ><br>
> >> > ><br>
> >> ><br>
> >><br>
> ><br>
> > _______________________________________________<br>
> > lldb-dev mailing list<br>
> > <a href="mailto:lldb-dev@cs.uiuc.edu">lldb-dev@cs.uiuc.edu</a><br>
> > <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev</a><br>
> ><br>
> _______________________________________________<br>
> lldb-dev mailing list<br>
> <a href="mailto:lldb-dev@cs.uiuc.edu">lldb-dev@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev</a><br>
<br>
_______________________________________________<br>
lldb-dev mailing list<br>
<a href="mailto:lldb-dev@cs.uiuc.edu">lldb-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev</a><br>
</div></div></blockquote></div><br></div>