diff --git a/Documentation/backend_test_health.md b/Documentation/backend_test_health.md index 9fd477a11..d20f75ef5 100644 --- a/Documentation/backend_test_health.md +++ b/Documentation/backend_test_health.md @@ -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 @@ -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 @@ -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 diff --git a/_fixtures/watchpointInterfaceNil.go b/_fixtures/watchpointInterfaceNil.go new file mode 100644 index 000000000..1e8412b9d --- /dev/null +++ b/_fixtures/watchpointInterfaceNil.go @@ -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) +} diff --git a/pkg/proc/breakpoints.go b/pkg/proc/breakpoints.go index ab6dcada3..fb42f88e2 100644 --- a/pkg/proc/breakpoints.go +++ b/pkg/proc/breakpoints.go @@ -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) } diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index 20faa9a44..27ac1c31c 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -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")