mirror of
https://github.com/go-delve/delve.git
synced 2025-11-02 12:59:01 +08:00
Automatically disable breakpoints with hitcount conditions that will never be satisfied again (#2833)
* service/debugger: disable breakpoints with hitcond not satisfiable To avoid slowing down the debugged process unnecessarily, we disable breakpoints with a hit condition that can no longer be hit again. * test: add integration tests for hit conditions no more satisfiable * proc/test: fix typo in breakpoints related tests * test: use the new API for hitcond integration tests
This commit is contained in:
@ -770,12 +770,10 @@ func (d *Debugger) CreateEBPFTracepoint(fnName string) error {
|
||||
return d.target.SetEBPFTracepoint(fnName)
|
||||
}
|
||||
|
||||
// AmendBreakpoint will update the breakpoint with the matching ID.
|
||||
// amendBreakpoint will update the breakpoint with the matching ID.
|
||||
// It also enables or disables the breakpoint.
|
||||
func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
|
||||
d.targetMutex.Lock()
|
||||
defer d.targetMutex.Unlock()
|
||||
|
||||
// We can consume this function to avoid locking a goroutine.
|
||||
func (d *Debugger) amendBreakpoint(amend *api.Breakpoint) error {
|
||||
originals := d.findBreakpoint(amend.ID)
|
||||
|
||||
if len(originals) > 0 && originals[0].WatchExpr != "" && amend.Disabled {
|
||||
@ -792,6 +790,17 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
|
||||
return err
|
||||
}
|
||||
copyBreakpointInfo(bp, amend)
|
||||
if breaklet := bp.UserBreaklet(); breaklet != nil {
|
||||
breaklet.TotalHitCount = amend.TotalHitCount
|
||||
breaklet.HitCount = map[int]uint64{}
|
||||
for idx := range amend.HitCount {
|
||||
i, err := strconv.Atoi(idx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't convert goroutine ID: %w", err)
|
||||
}
|
||||
breaklet.HitCount[i] = amend.HitCount[idx]
|
||||
}
|
||||
}
|
||||
delete(d.disabledBreakpoints, amend.ID)
|
||||
}
|
||||
if amend.Disabled && !disabled { // disable the breakpoint
|
||||
@ -809,6 +818,15 @@ func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AmendBreakpoint will update the breakpoint with the matching ID.
|
||||
// It also enables or disables the breakpoint.
|
||||
func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
|
||||
d.targetMutex.Lock()
|
||||
defer d.targetMutex.Unlock()
|
||||
|
||||
return d.amendBreakpoint(amend)
|
||||
}
|
||||
|
||||
// CancelNext will clear internal breakpoints, thus cancelling the 'next',
|
||||
// 'step' or 'stepout' operation.
|
||||
func (d *Debugger) CancelNext() error {
|
||||
@ -957,6 +975,33 @@ func (d *Debugger) clearBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoint
|
||||
return clearedBp, nil
|
||||
}
|
||||
|
||||
// isBpHitCondNotSatisfiable returns true if the breakpoint bp has a hit
|
||||
// condition that is no more satisfiable.
|
||||
// The hit condition is considered no more satisfiable if it can no longer be
|
||||
// hit again, for example with {Op: "==", Val: 1} and TotalHitCount == 1.
|
||||
func isBpHitCondNotSatisfiable(bp *api.Breakpoint) bool {
|
||||
if bp.HitCond == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
tok, val, err := parseHitCondition(bp.HitCond)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
switch tok {
|
||||
case token.EQL, token.LEQ:
|
||||
if int(bp.TotalHitCount) >= val {
|
||||
return true
|
||||
}
|
||||
case token.LSS:
|
||||
if int(bp.TotalHitCount) >= val-1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Breakpoints returns the list of current breakpoints.
|
||||
func (d *Debugger) Breakpoints(all bool) []*api.Breakpoint {
|
||||
d.targetMutex.Lock()
|
||||
@ -1284,6 +1329,10 @@ func (d *Debugger) Command(command *api.DebuggerCommand, resumeNotify chan struc
|
||||
}
|
||||
}
|
||||
}
|
||||
if bp := state.CurrentThread.Breakpoint; bp != nil && isBpHitCondNotSatisfiable(bp) {
|
||||
bp.Disabled = true
|
||||
d.amendBreakpoint(bp)
|
||||
}
|
||||
return state, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user