From 979e487ac7f187512c4a4c58567d5d742444a962 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 1 Jul 2024 20:23:39 +0200 Subject: [PATCH] service/debugger: evaluate breakpoint vars on g-less threads (#3759) Use a thread scope to evaluate breakpoint variables if the current thread does not have an associated goroutine. Fixes #3758 --- cmd/dlv/dlv_test.go | 2 +- service/debugger/debugger.go | 8 +++++++- service/test/integration2_test.go | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/cmd/dlv/dlv_test.go b/cmd/dlv/dlv_test.go index 9d3cea6924..c9fd264102 100644 --- a/cmd/dlv/dlv_test.go +++ b/cmd/dlv/dlv_test.go @@ -1082,7 +1082,7 @@ func TestTraceBreakpointExists(t *testing.T) { // We always set breakpoints on some runtime functions at startup, so this would return with // a breakpoints exists error. // TODO: Perhaps we shouldn't be setting these default breakpoints in trace mode, however. - cmd := exec.Command(dlvbin, "trace", "--output", filepath.Join(t.TempDir(), "__debug"), filepath.Join(fixtures, "issue573.go"), "runtime.*") + cmd := exec.Command(dlvbin, "trace", "--output", filepath.Join(t.TempDir(), "__debug"), filepath.Join(fixtures, "issue573.go"), "runtime.*panic") rdr, err := cmd.StderrPipe() assertNoError(err, t, "stderr pipe") defer rdr.Close() diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index 56e0aea1e2..5d3ed16033 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -1388,7 +1388,13 @@ func (d *Debugger) collectBreakpointInformation(apiThread *api.Thread, thread pr s, err := proc.GoroutineScope(tgt, thread) if err != nil { - return err + var errNoGoroutine proc.ErrNoGoroutine + if errors.As(err, &errNoGoroutine) { + s, err = proc.ThreadScope(tgt, thread) + } + if err != nil { + return err + } } if len(bp.Variables) > 0 { diff --git a/service/test/integration2_test.go b/service/test/integration2_test.go index b4b78692ac..6fc5f642d9 100644 --- a/service/test/integration2_test.go +++ b/service/test/integration2_test.go @@ -3153,3 +3153,17 @@ func TestNextInstruction(t *testing.T) { } }) } + +func TestBreakpointVariablesWithoutG(t *testing.T) { + // Tests that evaluating variables on a breakpoint that is hit on a thread + // without a goroutine does not cause an error. + withTestClient2("math", t, func(c service.Client) { + _, err := c.CreateBreakpoint(&api.Breakpoint{ + FunctionName: "runtime.mallocgc", + LoadArgs: &normalLoadConfig, + }) + assertNoError(err, t, "CreateBreakpoint") + state := <-c.Continue() + assertNoError(state.Err, t, "Continue()") + }) +}