Excellent, thanks! Jim
On Dec 7, 2012, at 9:58 AM, "Kaylor, Andrew" <[email protected]> wrote: > The solution Jim suggested below also fixes the problem. I've committed this > as r169618. > > -Andy > > -----Original Message----- > From: Pierre-Andre Saulais [mailto:[email protected]] > Sent: Friday, December 07, 2012 3:36 AM > To: Jim Ingham > Cc: Kaylor, Andrew; [email protected] > Subject: Re: [lldb-dev] Continue misfiring after expression evaluation > > I have run into the same problem with duplicated 'breakpoint stops' when > using expression evaluation on Linux. When setting the thread plans to > private in InferiorCallPOSIX.cpp as Andrew suggested, the issue does go away. > > Thanks Andrew! > > Pierre > > On 07/12/12 01:57, Jim Ingham wrote: >> Ah, right, that seems like another good way to do this (wonder who >> thought of and then forgot it...) >> >> I can't see a reason why function calling thread plans should ever be >> public. Even if you stop in the middle of one (because you called a >> function to break in it and step around) when you continue to finish the >> call you don't want the call function plan to be the reason you stopped back >> in normal code. >> >> So a better fix would be to set ThreadPlanCallFunction's to private in their >> constructor. >> >> BTW, We added an "allocate memory" packet to debugserver, so we don't need >> to use InferiorCallMmap. That's why we didn't see this on OSX. >> >> Jim >> >> >> On Dec 6, 2012, at 5:28 PM, "Kaylor, Andrew" <[email protected]> wrote: >> >>> Alright, this feels a lot better. >>> >>> After further investigation, I learned that Thread::GetStopInfo() only gets >>> the stop info from completed thread plans that aren't marked private. >>> Looking around at some examples in the code, it seemed that the thread >>> plans involved in the expression evaluation should have been marked >>> private, at least before the Process object started executing them. I >>> verified that Process::RunThreadPlan was saving and restoring the >>> ThreadPlan's 'private' state correctly but that my ThreadPlanRunFunction >>> was entering with 'private' set to false. >>> >>> I was able to track this thread plan back to InferiorCallMmap in >>> InferiorCallPOSIX.cpp. I'm guessing that Mac OS X doesn't use that for >>> whatever reason. >>> >>> The attached patch fixes the problem I was investigating and it seems like >>> a reasonable change. Can you review this, Jim? >>> >>> Thanks, >>> Andy >>> >>> -----Original Message----- >>> From: Jim Ingham [mailto:[email protected]] >>> Sent: Thursday, December 06, 2012 2:28 PM >>> To: Kopec, Matt >>> Cc: Kaylor, Andrew; [email protected]; Malea, Daniel >>> Subject: Re: [lldb-dev] Continue misfiring after expression >>> evaluation >>> >>> I don't see this fail, even for function calls: >>> >>> (lldb) b s -n main >>> Breakpoint 1: 3 locations. >>> (lldb) run >>> Process 96310 launched: >>> '/Users/jingham/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS >>> /Sketch' (x86_64) Process 96310 stopped >>> * thread #1: tid = 0x1c03, function: main , stop reason = breakpoint 1.1 >>> frame #0: 0x000000010001a74e Sketch`main at SKTMain.m:11 >>> 8 >>> 9 >>> 10 int main(int argc, const char *argv[]) { >>> -> 11 NSLog (@"Added for testing rebuilds."); >>> 12 const char *names[20]; >>> 13 for (int i = 0; i < argc; i++) >>> 14 { >>> (lldb) expr (int) printf ("Some text here.\n") >>> (int) $0 = 16 >>> Some text here. >>> (lldb) log enable lldb step >>> (lldb) c >>> <lldb.driver.main-thread> Pushing plan: "Single stepping past breakpoint >>> site 3 at 0x10001a74e", tid = 0x1c03. >>> <lldb.driver.main-thread> ThreadPlanCallFunction(0x7f8eb4189540): >>> DoTakedown called as no-op for thread 0x1c03, m_valid: 1 complete: 1. >>> >>> <lldb.driver.main-thread> WillResume Thread #1: tid = 0x1c03, pc = >>> 0x10001a74e, sp = 0x7fff5fbff4a0, fp = 0x7fff5fbff5e0, plan = 'Step over >>> breakpoint trap', state = stepping, stop others = 1 >>> <lldb.process.internal-state(pid=96310)> Current Plan for thread 1 >>> (0x1c03): Step over breakpoint trap being asked whether we should report >>> run. >>> Process 96310 resuming >>> <lldb.process.internal-state(pid=96310)> >>> <lldb.process.internal-state(pid=96310)> ThreadList::ShouldStop: 1 threads >>> <lldb.process.internal-state(pid=96310)> Thread::ShouldStop for tid = >>> 0x1c03, pc = 0x000000010001a751 <lldb.process.internal-state(pid=96310)> >>> ^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^ >>> <lldb.process.internal-state(pid=96310)> Plan stack initial state: >>> Plan Stack for thread #1: tid = 0x1c03, stack_size = 2 >>> Element 1: Single stepping past breakpoint site 3 at 0x10001a74e >>> Element 0: Base thread plan. >>> >>> <lldb.process.internal-state(pid=96310)> Plan Step over breakpoint trap >>> explains stop, auto-continue 1. >>> <lldb.process.internal-state(pid=96310)> Plan Step over breakpoint trap >>> should stop: 0. >>> <lldb.process.internal-state(pid=96310)> Completed step over breakpoint >>> plan. >>> <lldb.process.internal-state(pid=96310)> Popping plan: "Step over >>> breakpoint trap", tid = 0x1c03. >>> <lldb.process.internal-state(pid=96310)> Plan stack final state: >>> Plan Stack for thread #1: tid = 0x1c03, stack_size = 1 >>> Element 0: Base thread plan. >>> Completed Plan Stack: 1 elements. >>> Element 0: Single stepping past breakpoint site 3 at 0x10001a74e >>> >>> The call to printf definitely ran code in the target, and yet >>> continue pushed the "step over breakpoint" plan rather than stopping >>> with another breakpoint hit (which is what I presume you are seeing?) >>> >>> Jim >>> >>> >>> On Dec 6, 2012, at 1:01 PM, "Kopec, Matt" <[email protected]> wrote: >>> >>>> Daniel and I saw the same behaviour as Andy on Mac recently though we >>>> reproduced it differently. If I recall what was happening on Mac >>>> correctly, the expression to be evaluated didn't require MCJIT/executing >>>> in the target process (for instance, printing a register value - expr pc) >>>> but on Linux did require MCJIT/running in the target. However, evaluating >>>> a function call expression did reproduce the problem on Mac since this did >>>> go through the MCJIT route. Could you try this to see if it reproduces the >>>> problem? >>>> >>>> Thanks, >>>> Matt >>>> ________________________________________ >>>> From: [email protected] [[email protected]] on >>>> behalf of Jim Ingham [[email protected]] >>>> Sent: Thursday, December 06, 2012 2:05 PM >>>> To: Kaylor, Andrew >>>> Cc: [email protected] >>>> Subject: Re: [lldb-dev] Continue misfiring after expression >>>> evaluation >>>> >>>> Yeah, after taking a quick look at the code last night, I'm curious too. >>>> >>>> I am in the middle of something right now, but as soon as I get a chance, >>>> I'll step through it and see what's going on. >>>> >>>> Thinking about it a little bit more, I can't see any reason why >>>> Process::RunThreadPlan should not clear the evidence of its work from the >>>> plan stack. It should only do this if the plan succeeds, or if it is >>>> going to unwind on error. If you're going to stop because you hit a >>>> breakpoint in the middle of a function call, you don't want to change the >>>> plan stack state (just like you don't want to restore the old stop info.) >>>> And I think it would be wrong to erase the whole completed plan stack, >>>> better to mark the position on entry, and restore it to the state it had >>>> when you entered RunThreadPlan. >>>> >>>> Jim >>>> >>>> On Dec 6, 2012, at 10:54 AM, "Kaylor, Andrew" <[email protected]> >>>> wrote: >>>> >>>>> I updated to the latest code and I'm still seeing the same behavior. >>>>> >>>>> That is, thread_plan_sp->RestoreThreadState() is being called, and it >>>>> does restore the stop info for the thread to the old stop info, but when >>>>> Thread::SetupForResume() calls Thread::GetStopInfo() that function >>>>> creates stop info based on the completed thread plan stack rather than >>>>> using m_actual_stop_info_sp. >>>>> >>>>> Any suggestions? I'd be curious to know why this doesn't happen on Mac >>>>> OS X because it looks like it would. >>>>> >>>>> -Andy >>>>> >>>>> -----Original Message----- >>>>> From: [email protected] >>>>> [mailto:[email protected]] On Behalf Of Kaylor, Andrew >>>>> Sent: Wednesday, December 05, 2012 4:38 PM >>>>> To: Jim Ingham >>>>> Cc: [email protected] >>>>> Subject: Re: [lldb-dev] Continue misfiring after expression >>>>> evaluation >>>>> >>>>> Hi Jim, >>>>> >>>>> I am working with an old version of the code, so things were in a bit >>>>> different state for me. I was seeing >>>>> Thread::RestoreThreadStateFromCheckpoint() being called. The problem is >>>>> that when Thread::SetupForResume() calls Thread::GetStopInfo(), the >>>>> latter does this: >>>>> >>>>> ThreadPlanSP plan_sp (GetCompletedPlan()); >>>>> if (plan_sp && plan_sp->PlanSucceeded()) >>>>> return StopInfo::CreateStopReasonWithPlan (plan_sp, >>>>> GetReturnValueObject()); >>>>> else >>>>> { >>>>> ProcessSP process_sp (GetProcess()); >>>>> if (process_sp >>>>> && m_actual_stop_info_sp >>>>> && m_actual_stop_info_sp->IsValid() >>>>> && m_thread_stop_reason_stop_id == process_sp->GetStopID()) >>>>> return m_actual_stop_info_sp; >>>>> else >>>>> return GetPrivateStopReason (); >>>>> } >>>>> >>>>> Since the completed stop plan from the expression command is still >>>>> around, the stop info comes from there. The thread's m_actual_stop_info >>>>> seems to be correct, but the code doesn't get to the point where it would >>>>> use it. >>>>> >>>>> I'll update to the latest code and see if this is still happening, but I >>>>> wanted to tell you what I knew while I was still in a known state. I'll >>>>> let you know what happens with the new code. >>>>> >>>>> -Andy >>>>> >>>>> -----Original Message----- >>>>> From: Jim Ingham [mailto:[email protected]] >>>>> Sent: Wednesday, December 05, 2012 3:50 PM >>>>> To: Kaylor, Andrew >>>>> Cc: [email protected] >>>>> Subject: Re: [lldb-dev] Continue misfiring after expression >>>>> evaluation >>>>> >>>>> I don't see this happening on Mac OS X. That test succeeds, and I don't >>>>> see the behavior you describe. >>>>> >>>>> You should not need to clear the completed plan stack. The way it is >>>>> supposed to work is as follows: >>>>> >>>>> Running functions is always done by Process::RunThreadPlan. After the >>>>> ThreadPlanCallFunction gets done running in that function, we do this bit >>>>> of code: >>>>> >>>>> // Restore the thread state if we are going to discard the plan >>>>> execution. >>>>> >>>>> if (return_value == eExecutionCompleted || discard_on_error) >>>>> { >>>>> thread_plan_sp->RestoreThreadState(); >>>>> } >>>>> >>>>> That should set the StopInfo that was squirreled away in >>>>> Thread::CheckpointThreadState back as the current StopInfo for the >>>>> thread. Is that getting called? If not, why not? If it is getting >>>>> called, why isn't it succeeding in resetting the thread's StopInfo back >>>>> to the old reason? >>>>> >>>>> Note, up till a couple of weeks ago this work was done in the DoTakedown >>>>> method of ThreadPlanCallFunction, but I moved resetting the StopInfo out >>>>> of that function (which gets called while the stop event for the function >>>>> call is still being processed) to here, because otherwise it might >>>>> trigger the original StopInfo's PerformAction while you are in the middle >>>>> of handing the ThreadPlanCallFunction's execution, which isn't right. >>>>> >>>>> Hope that helps. >>>>> >>>>> Jim >>>>> >>>>> On Dec 5, 2012, at 3:28 PM, "Kaylor, Andrew" <[email protected]> >>>>> wrote: >>>>> >>>>>> Hi all, >>>>>> >>>>>> I've been debugging a problem on Linux where if you hit a breakpoint, >>>>>> then evaluate an expression that requires JITing, then continue LLDB >>>>>> will break at the line you were already on. I don't know if this >>>>>> problem is specific to Linux, but that's where I'm debugging it. This >>>>>> problem appears in the 'lang/c/setvalues/TestSetValues.py' test case, >>>>>> but can also be reproduced manually. >>>>>> >>>>>> What I'm seeing is that when the 'continue' handling calls >>>>>> Thread::SetupForResume() the current Thread reports its stop reason as >>>>>> 'eStopReasonPlanComplete' because the ThreadPlan for evaluating the >>>>>> expression is still on the completed plans stack. As a result, the >>>>>> ThreadPlanStepOverBreakpoint plan doesn't get queued. If I add calls to >>>>>> 'm_completed_plan_stack.clear()' and 'm_discarded_plan_stack.clear()' at >>>>>> the top of the 'if (GetResumeState() == eStateSuspended)' block in >>>>>> Thread::SetupForResume() then everything works as expected. >>>>>> >>>>>> Obviously, that feels like a pretty risky thing to do, at best. It >>>>>> seems like the expression command handling should have done something to >>>>>> clear the completed plan stack when it was finished, but as of yet I >>>>>> haven't found a place where that is appropriate. >>>>>> >>>>>> Can anyone give me guidance on this issue? >>>>>> >>>>>> Thanks, >>>>>> Andy >>>>>> _______________________________________________ >>>>>> lldb-dev mailing list >>>>>> [email protected] >>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev >>>>> >>>>> _______________________________________________ >>>>> lldb-dev mailing list >>>>> [email protected] >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev >>>> _______________________________________________ >>>> lldb-dev mailing list >>>> [email protected] >>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev >>> <make-mmap-thread-plan-private.patch> >> _______________________________________________ >> lldb-dev mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev > _______________________________________________ lldb-dev mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
