mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 17:56:45 +08:00
terminal: add prompt when breakpoint is hit during next/step/stepout (#2548)
* terminal: add prompt when breakpoint is hit during next/step/stepout Adds a prompt asking the user what to do when a breakpoint is hit on a different goroutine while next/step/stepout is being executed. Gives the user the opportunity to cancel next/step/stepout, continue once skipping the breakpoint or automatically skipping all other concurrent breakpoints until next/step/stepout is finished. Fixes #2317
This commit is contained in:
committed by
GitHub
parent
e9b20d5ee1
commit
2ecc025311
@ -1446,8 +1446,28 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, sho
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
skipBreakpoints := false
|
||||||
for {
|
for {
|
||||||
fmt.Printf("\tbreakpoint hit during %s, continuing...\n", op)
|
fmt.Printf("\tbreakpoint hit during %s", op)
|
||||||
|
if !skipBreakpoints {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
answer, err := promptAutoContinue(t, op)
|
||||||
|
switch answer {
|
||||||
|
case "f": // finish next
|
||||||
|
skipBreakpoints = true
|
||||||
|
fallthrough
|
||||||
|
case "c": // continue once
|
||||||
|
fmt.Printf("continuing...\n")
|
||||||
|
case "s": // stop and cancel
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
t.client.CancelNext()
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf(", continuing...\n")
|
||||||
|
}
|
||||||
stateChan := t.client.DirectionCongruentContinue()
|
stateChan := t.client.DirectionCongruentContinue()
|
||||||
var state *api.DebuggerState
|
var state *api.DebuggerState
|
||||||
for state = range stateChan {
|
for state = range stateChan {
|
||||||
@ -1464,6 +1484,20 @@ func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, sho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func promptAutoContinue(t *Term, op string) (string, error) {
|
||||||
|
for {
|
||||||
|
answer, err := t.line.Prompt(fmt.Sprintf("[c] continue [s] stop here and cancel %s, [f] finish %s skipping all breakpoints? ", op, op))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
answer = strings.ToLower(strings.TrimSpace(answer))
|
||||||
|
switch answer {
|
||||||
|
case "f", "c", "s":
|
||||||
|
return answer, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func scopePrefixSwitch(t *Term, ctx callContext) error {
|
func scopePrefixSwitch(t *Term, ctx callContext) error {
|
||||||
if ctx.Scope.GoroutineID > 0 {
|
if ctx.Scope.GoroutineID > 0 {
|
||||||
_, err := t.client.SwitchGoroutine(ctx.Scope.GoroutineID)
|
_, err := t.client.SwitchGoroutine(ctx.Scope.GoroutineID)
|
||||||
|
|||||||
@ -582,47 +582,6 @@ func countOccurrences(s, needle string) int {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue387(t *testing.T) {
|
|
||||||
if runtime.GOOS == "freebsd" {
|
|
||||||
t.Skip("test is not valid on FreeBSD")
|
|
||||||
}
|
|
||||||
// a breakpoint triggering during a 'next' operation will interrupt it
|
|
||||||
test.AllowRecording(t)
|
|
||||||
withTestTerminal("issue387", t, func(term *FakeTerminal) {
|
|
||||||
breakpointHitCount := 0
|
|
||||||
term.MustExec("break dostuff")
|
|
||||||
for {
|
|
||||||
outstr, err := term.Exec("continue")
|
|
||||||
breakpointHitCount += countOccurrences(outstr, "issue387.go:8")
|
|
||||||
t.Log(outstr)
|
|
||||||
if err != nil {
|
|
||||||
if !strings.Contains(err.Error(), "exited") {
|
|
||||||
t.Fatalf("Unexpected error executing 'continue': %v", err)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
pos := 9
|
|
||||||
|
|
||||||
for {
|
|
||||||
outstr = term.MustExec("next")
|
|
||||||
breakpointHitCount += countOccurrences(outstr, "issue387.go:8")
|
|
||||||
t.Log(outstr)
|
|
||||||
if countOccurrences(outstr, fmt.Sprintf("issue387.go:%d", pos)) == 0 {
|
|
||||||
t.Fatalf("did not continue to expected position %d", pos)
|
|
||||||
}
|
|
||||||
pos++
|
|
||||||
if pos >= 11 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if breakpointHitCount != 10 {
|
|
||||||
t.Fatalf("Breakpoint hit wrong number of times, expected 10 got %d", breakpointHitCount)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func listIsAt(t *testing.T, term *FakeTerminal, listcmd string, cur, start, end int) {
|
func listIsAt(t *testing.T, term *FakeTerminal, listcmd string, cur, start, end int) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
outstr := term.MustExec(listcmd)
|
outstr := term.MustExec(listcmd)
|
||||||
|
|||||||
Reference in New Issue
Block a user