提交 5c2673a6 编写于 作者: A aarzilli 提交者: Derek Parker

proc/native, proc/gdbserial: StepInstruction without goroutine

proc.Process.StepInstruction should work even if there is no goroutine
selected.
上级 e9e08300
...@@ -623,25 +623,26 @@ continueLoop: ...@@ -623,25 +623,26 @@ continueLoop:
} }
func (p *Process) StepInstruction() error { func (p *Process) StepInstruction() error {
if p.selectedGoroutine == nil { thread := p.currentThread
return errors.New("cannot single step: no selected goroutine") if p.selectedGoroutine != nil {
} if p.selectedGoroutine.Thread == nil {
if p.selectedGoroutine.Thread == nil { if _, err := p.SetBreakpoint(p.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(p.selectedGoroutine)); err != nil {
if _, err := p.SetBreakpoint(p.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(p.selectedGoroutine)); err != nil { return err
return err }
return proc.Continue(p)
} }
return proc.Continue(p) thread = p.selectedGoroutine.Thread.(*Thread)
} }
p.allGCache = nil p.allGCache = nil
if p.exited { if p.exited {
return &proc.ProcessExitedError{Pid: p.conn.pid} return &proc.ProcessExitedError{Pid: p.conn.pid}
} }
p.selectedGoroutine.Thread.(*Thread).clearBreakpointState() thread.clearBreakpointState()
err := p.selectedGoroutine.Thread.(*Thread).StepInstruction() err := thread.StepInstruction()
if err != nil { if err != nil {
return err return err
} }
return p.selectedGoroutine.Thread.(*Thread).SetCurrentBreakpoint() return thread.SetCurrentBreakpoint()
} }
func (p *Process) SwitchThread(tid int) error { func (p *Process) SwitchThread(tid int) error {
......
package native package native
import ( import (
"errors"
"fmt" "fmt"
"go/ast" "go/ast"
"os" "os"
...@@ -297,26 +296,27 @@ func (dbp *Process) ContinueOnce() (proc.Thread, error) { ...@@ -297,26 +296,27 @@ func (dbp *Process) ContinueOnce() (proc.Thread, error) {
// asssociated with the selected goroutine. All other // asssociated with the selected goroutine. All other
// threads will remain stopped. // threads will remain stopped.
func (dbp *Process) StepInstruction() (err error) { func (dbp *Process) StepInstruction() (err error) {
if dbp.selectedGoroutine == nil { thread := dbp.currentThread
return errors.New("cannot single step: no selected goroutine") if dbp.selectedGoroutine != nil {
} if dbp.selectedGoroutine.Thread == nil {
if dbp.selectedGoroutine.Thread == nil { // Step called on parked goroutine
// Step called on parked goroutine if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(dbp.selectedGoroutine)); err != nil {
if _, err := dbp.SetBreakpoint(dbp.selectedGoroutine.PC, proc.NextBreakpoint, proc.SameGoroutineCondition(dbp.selectedGoroutine)); err != nil { return err
return err }
return proc.Continue(dbp)
} }
return proc.Continue(dbp) thread = dbp.selectedGoroutine.Thread.(*Thread)
} }
dbp.allGCache = nil dbp.allGCache = nil
if dbp.exited { if dbp.exited {
return &proc.ProcessExitedError{} return &proc.ProcessExitedError{}
} }
dbp.selectedGoroutine.Thread.(*Thread).clearBreakpointState() thread.clearBreakpointState()
err = dbp.selectedGoroutine.Thread.(*Thread).StepInstruction() err = thread.StepInstruction()
if err != nil { if err != nil {
return err return err
} }
return dbp.selectedGoroutine.Thread.(*Thread).SetCurrentBreakpoint() return thread.SetCurrentBreakpoint()
} }
// SwitchThread changes from current thread to the thread specified by `tid`. // SwitchThread changes from current thread to the thread specified by `tid`.
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/derekparker/delve/pkg/dwarf/frame"
"github.com/derekparker/delve/pkg/proc" "github.com/derekparker/delve/pkg/proc"
"github.com/derekparker/delve/pkg/proc/gdbserial" "github.com/derekparker/delve/pkg/proc/gdbserial"
"github.com/derekparker/delve/pkg/proc/native" "github.com/derekparker/delve/pkg/proc/native"
...@@ -2954,3 +2955,29 @@ func TestIssue877(t *testing.T) { ...@@ -2954,3 +2955,29 @@ func TestIssue877(t *testing.T) {
} }
}) })
} }
func TestIssue893(t *testing.T) {
// Test what happens when next is called immediately after launching the
// executable, acceptable behaviors are: (a) no error, (b) no source at PC
// error.
protest.AllowRecording(t)
withTestProcess("increment", t, func(p proc.Process, fixture protest.Fixture) {
err := proc.Next(p)
if err == nil {
return
}
if _, ok := err.(*frame.NoFDEForPCError); ok {
return
}
assertNoError(err, t, "Next")
})
}
func TestStepInstructionNoGoroutine(t *testing.T) {
protest.AllowRecording(t)
withTestProcess("increment", t, func(p proc.Process, fixture protest.Fixture) {
// Call StepInstruction immediately after launching the program, it should
// work even though no goroutine is selected.
assertNoError(p.StepInstruction(), t, "StepInstruction")
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册