From 1024191ee59326488af304173f5ea39e4afe18ef Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 14 Sep 2022 17:03:45 +0200 Subject: [PATCH] Debugger: Fix breakpoint with "HitCount" do not eval stack/watches until hit-count is reached (for FpDebug backend) --- components/debuggerintf/dbgintfdebuggerbase.pp | 17 +++++++++++++---- .../lazdebuggerfp/fpdebugdebugger.pas | 12 +++++++++--- ide/packages/idedebugger/debugger.pp | 9 ++++++--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/components/debuggerintf/dbgintfdebuggerbase.pp b/components/debuggerintf/dbgintfdebuggerbase.pp index 29e0921b38..f7dec49639 100644 --- a/components/debuggerintf/dbgintfdebuggerbase.pp +++ b/components/debuggerintf/dbgintfdebuggerbase.pp @@ -289,7 +289,7 @@ type protected procedure AssignLocationTo(Dest: TPersistent); virtual; procedure AssignTo(Dest: TPersistent); override; - procedure DoHit(const ACount: Integer; var {%H-}AContinue: Boolean); virtual; + procedure DoHit(const ACount: Integer; var {%H-}AContinue, ANeedInternalPause: Boolean); virtual; procedure SetHitCount(const AValue: Integer); procedure SetValid(const AValue: TValidState); protected @@ -362,6 +362,7 @@ type constructor Create(ACollection: TCollection); override; destructor Destroy; override; procedure Hit(var ACanContinue: Boolean); + procedure Hit(var ACanContinue, ANeedInternalPause: Boolean); property Slave: TBaseBreakPoint read FSlave write SetSlave; property Kind: TDBGBreakPointKind read GetKind write SetKind; // TODO: remove, used by TIDEBreakPoint.SetKind @@ -3316,7 +3317,8 @@ begin Changed; end; -procedure TBaseBreakPoint.DoHit(const ACount: Integer; var AContinue: Boolean ); +procedure TBaseBreakPoint.DoHit(const ACount: Integer; var AContinue, + ANeedInternalPause: Boolean); begin SetHitCount(ACount); end; @@ -3457,15 +3459,22 @@ begin end; procedure TDBGBreakPoint.Hit(var ACanContinue: Boolean); +var + dummy: Boolean; +begin + Hit(ACanContinue, dummy); +end; + +procedure TDBGBreakPoint.Hit(var ACanContinue, ANeedInternalPause: Boolean); var cnt: Integer; begin cnt := HitCount + 1; if BreakHitcount > 0 then ACanContinue := cnt < BreakHitcount; - DoHit(cnt, ACanContinue); + DoHit(cnt, ACanContinue, ANeedInternalPause); if Assigned(FSlave) - then FSlave.DoHit(cnt, ACanContinue); + then FSlave.DoHit(cnt, ACanContinue, ANeedInternalPause); Debugger.DoBreakpointHit(Self, ACanContinue) end; diff --git a/components/lazdebuggers/lazdebuggerfp/fpdebugdebugger.pas b/components/lazdebuggers/lazdebuggerfp/fpdebugdebugger.pas index 3cb13fe613..7296762722 100644 --- a/components/lazdebuggers/lazdebuggerfp/fpdebugdebugger.pas +++ b/components/lazdebuggers/lazdebuggerfp/fpdebugdebugger.pas @@ -333,7 +333,7 @@ type *) FWorkerThreadId: TThreadID; FEvalWorkItem: TFpThreadWorkerCmdEval; - FQuickPause, FPauseForEvent, FSendingEvents: boolean; + FQuickPause, FPauseForEvent, FInternalPauseForEvent, FSendingEvents: boolean; FExceptionStepper: TFpDebugExceptionStepping; FConsoleOutputThread: TThread; // Helper vars to run in debug-thread @@ -3543,8 +3543,10 @@ var Context: TFpDbgSymbolScope; PasExpr: TFpPascalExpression; Opts: TFpInt3DebugBreakOptions; + NeedInternalPause: Boolean; begin // If a user single steps to an excepiton handler, do not open the dialog (there is no continue possible) + NeedInternalPause := False; if AnEventType = deBreakpoint then if FExceptionStepper.BreakpointHit(&continue, Breakpoint) then exit; @@ -3582,7 +3584,7 @@ begin EventLogHandler.LogEventBreakPointHit(ABreakpoint, ALocationAddr); if assigned(ABreakPoint) then - ABreakPoint.Hit(&continue); + ABreakPoint.Hit(&continue, NeedInternalPause); if (not &continue) and (ABreakPoint.Kind = bpkData) and (OnFeedback <> nil) then begin // For message use location(Address - 1) @@ -3621,8 +3623,11 @@ begin if not continue then FPauseForEvent := True; - if not AMoreHitEventsPending then begin + FInternalPauseForEvent := FInternalPauseForEvent or NeedInternalPause; + + if (not AMoreHitEventsPending) and (FPauseForEvent or FInternalPauseForEvent) then begin FQuickPause := False; // Ok, because we will SetState => RunQuickPauseTasks is not needed + if FPauseForEvent then &continue := False; // Only continue, if ALL events did say to continue @@ -3944,6 +3949,7 @@ begin Threads.CurrentThreads.CurrentThreadId := FDbgController.CurrentThreadId; FPauseForEvent := False; + FInternalPauseForEvent := False; FSendingEvents := True; try FDbgController.SendEvents(Cont); // This may free the TFpDebugDebugger (self) diff --git a/ide/packages/idedebugger/debugger.pp b/ide/packages/idedebugger/debugger.pp index bb1b914afe..bb2950f467 100644 --- a/ide/packages/idedebugger/debugger.pp +++ b/ide/packages/idedebugger/debugger.pp @@ -316,7 +316,7 @@ type procedure DisableGroups; procedure DoActionChange; virtual; - procedure DoHit(const ACount: Integer; var AContinue: Boolean); override; + procedure DoHit(const ACount: Integer; var AContinue, ANeedInternalPause: Boolean); override; procedure EnableGroups; procedure ClearAllGroupLists; {$IFDEF DBG_BREAKPOINT} @@ -5634,9 +5634,10 @@ begin DoUserChanged; end; -procedure TIDEBreakPoint.DoHit(const ACount: Integer; var AContinue: Boolean); +procedure TIDEBreakPoint.DoHit(const ACount: Integer; var AContinue, + ANeedInternalPause: Boolean); begin - inherited DoHit(ACount, AContinue); + inherited DoHit(ACount, AContinue, ANeedInternalPause); AContinue := AContinue or not (bpaStop in Actions); if bpaLogMessage in Actions then Master.DoLogMessage(FLogMessage); @@ -5645,6 +5646,8 @@ begin if bpaLogCallStack in Actions then Master.DoLogCallStack(FLogCallStackLimit); // SnapShot is taken in TDebugManager.DebuggerChangeState + if bpaTakeSnapshot in Actions then + ANeedInternalPause := True; if bpaEnableGroup in Actions then EnableGroups; if bpaDisableGroup in Actions