Skip to content

Commit

Permalink
pkg/proc: support watchpoint on nil interface (#3924)
Browse files Browse the repository at this point in the history
  • Loading branch information
derekparker authored Feb 28, 2025
1 parent 2880422 commit 1df310a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 16 deletions.
24 changes: 12 additions & 12 deletions Documentation/backend_test_health.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Tests skipped by each supported backend:

* 386 skipped = 10
* 386 skipped = 11
* 1 broken
* 3 broken - cgo stacktraces
* 5 not implemented
* 6 not implemented
* 1 not working due to optimizations
* arm64 skipped = 1
* 1 broken - global variable symbolication
Expand All @@ -14,10 +14,10 @@ Tests skipped by each supported backend:
* 1 broken - cgo stacktraces
* darwin/lldb skipped = 1
* 1 upstream issue
* freebsd skipped = 12
* freebsd skipped = 13
* 2 flaky
* 2 follow exec not implemented on freebsd
* 6 not implemented
* 7 not implemented
* 2 not working on freebsd
* linux/386 skipped = 2
* 2 not working on linux/386
Expand All @@ -36,24 +36,24 @@ Tests skipped by each supported backend:
* linux/riscv64 skipped = 2
* 1 broken - cgo stacktraces
* 1 not working on linux/riscv64
* loong64 skipped = 8
* loong64 skipped = 9
* 2 broken
* 1 broken - global variable symbolication
* 5 not implemented
* 6 not implemented
* pie skipped = 2
* 2 upstream issue - https://github.com/golang/go/issues/29322
* ppc64le skipped = 13
* ppc64le skipped = 14
* 6 broken
* 1 broken - global variable symbolication
* 6 not implemented
* riscv64 skipped = 7
* 7 not implemented
* riscv64 skipped = 8
* 2 broken
* 1 broken - global variable symbolication
* 4 not implemented
* windows skipped = 8
* 5 not implemented
* windows skipped = 9
* 1 broken
* 2 not working on windows
* 5 see https://github.com/go-delve/delve/issues/2768
* 6 see https://github.com/go-delve/delve/issues/2768
* windows/arm64 skipped = 5
* 3 broken
* 1 broken - cgo stacktraces
Expand Down
15 changes: 15 additions & 0 deletions _fixtures/watchpointInterfaceNil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"errors"
"fmt"
)

func main() {
var err error
fmt.Println("Error created:", err)
err = errors.New("modified error")
fmt.Println("Error modified:", err)
err = errors.New("final modified error")
fmt.Println("Error modified final:", err)
}
5 changes: 1 addition & 4 deletions pkg/proc/breakpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -649,13 +649,10 @@ func (t *Target) SetWatchpoint(logicalID int, scope *EvalScope, expr string, wty
if xv.Kind == reflect.Interface {
// For interfaces, we want to watch the data they point to
// Read the interface to get the data pointer
_, data, isnil := xv.readInterface()
_, data, _ := xv.readInterface()
if xv.Unreadable != nil {
return nil, fmt.Errorf("error reading interface %q: %v", expr, xv.Unreadable)
}
if isnil {
return nil, fmt.Errorf("can not watch nil interface %q", expr)
}
if data == nil {
return nil, fmt.Errorf("invalid interface %q", expr)
}
Expand Down
40 changes: 40 additions & 0 deletions pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5575,6 +5575,46 @@ func TestWatchpointInterface(t *testing.T) {
})
}

func TestWatchpointInterfaceNil(t *testing.T) {
skipOn(t, "not implemented", "freebsd")
skipOn(t, "not implemented", "386")
skipOn(t, "not implemented", "ppc64le")
skipOn(t, "not implemented", "riscv64")
skipOn(t, "not implemented", "loong64")
skipOn(t, "see https://github.com/go-delve/delve/issues/2768", "windows")
protest.AllowRecording(t)

withTestProcess("watchpointInterfaceNil", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
// Set breakpoint at line after error is created and printed
setFileBreakpoint(p, t, fixture.Source, 10)
assertNoError(grp.Continue(), t, "Continue()")
assertLineNumber(p, t, 10, "continued to wrong line")

// Get scope and set watchpoint on interface type
scope, err := proc.GoroutineScope(p, p.CurrentThread())
assertNoError(err, t, "GoroutineScope")

// Set watchpoint on the error interface
_, err = p.SetWatchpoint(0, scope, "err", proc.WatchWrite, nil)
assertNoError(err, t, "SetWatchpoint on interface type")

// Continue to hit the watchpoint when the error is modified
assertNoError(grp.Continue(), t, "Continue to watchpoint")

// Verify we stopped at the correct line where err is modified
assertLineNumberIn(p, t, []int{11, 12}, "stopped at wrong line after interface watchpoint")

// Continue to hit the watchpoint when the error is modified again
assertNoError(grp.Continue(), t, "Continue to watchpoint (2)")

// Verify we stopped at the correct line where err is modified
assertLineNumberIn(p, t, []int{13, 14}, "stopped at wrong line after interface watchpoint (2)")

// Continue to the end
assertNoError(grp.Continue(), t, "Final continue")
})
}

func TestStackwatchClearBug(t *testing.T) {
skipOn(t, "not implemented", "freebsd")
skipOn(t, "not implemented", "386")
Expand Down

0 comments on commit 1df310a

Please sign in to comment.