提交 cc63d209 编写于 作者: D Derek Parker 提交者: Alessandro Arzilli

pkg/proc: return proper error when debugger has exited

Instead of panicing for sending on a closed channel, detect that the
process has exited and return a proper error message.

This patch also cleans up some spots where the Pid is omitted from the
error.

Fixes #920
上级 d7a92b58
......@@ -21,6 +21,9 @@ const (
// If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble will evaluate the argument of the CALL instruction using the thread's registers
// Be aware that the Bytes field of each returned instruction is a slice of a larger array of size endPC - startPC
func Disassemble(dbp Process, g *G, startPC, endPC uint64) ([]AsmInstruction, error) {
if dbp.Exited() {
return nil, &ProcessExitedError{Pid: dbp.Pid()}
}
if g == nil {
ct := dbp.CurrentThread()
regs, _ := ct.Registers(false)
......
......@@ -173,7 +173,7 @@ func (dbp *Process) LoadInformation(path string) error {
// sends SIGSTOP to all threads.
func (dbp *Process) RequestManualStop() error {
if dbp.exited {
return &proc.ProcessExitedError{}
return &proc.ProcessExitedError{Pid: dbp.Pid()}
}
dbp.haltMu.Lock()
defer dbp.haltMu.Unlock()
......@@ -241,7 +241,7 @@ func (dbp *Process) SetBreakpoint(addr uint64, kind proc.BreakpointKind, cond as
// ClearBreakpoint clears the breakpoint at addr.
func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
if dbp.exited {
return nil, &proc.ProcessExitedError{}
return nil, &proc.ProcessExitedError{Pid: dbp.Pid()}
}
bp, ok := dbp.FindBreakpoint(addr)
if !ok {
......@@ -259,7 +259,7 @@ func (dbp *Process) ClearBreakpoint(addr uint64) (*proc.Breakpoint, error) {
func (dbp *Process) ContinueOnce() (proc.Thread, error) {
if dbp.exited {
return nil, &proc.ProcessExitedError{}
return nil, &proc.ProcessExitedError{Pid: dbp.Pid()}
}
if err := dbp.resume(); err != nil {
......@@ -307,7 +307,7 @@ func (dbp *Process) StepInstruction() (err error) {
}
dbp.allGCache = nil
if dbp.exited {
return &proc.ProcessExitedError{}
return &proc.ProcessExitedError{Pid: dbp.Pid()}
}
thread.clearBreakpointState()
err = thread.StepInstruction()
......@@ -327,7 +327,7 @@ func (dbp *Process) StepInstruction() (err error) {
// SwitchThread changes from current thread to the thread specified by `tid`.
func (dbp *Process) SwitchThread(tid int) error {
if dbp.exited {
return &proc.ProcessExitedError{}
return &proc.ProcessExitedError{Pid: dbp.Pid()}
}
if th, ok := dbp.threads[tid]; ok {
dbp.currentThread = th
......@@ -341,7 +341,7 @@ func (dbp *Process) SwitchThread(tid int) error {
// running the specified goroutine.
func (dbp *Process) SwitchGoroutine(gid int) error {
if dbp.exited {
return &proc.ProcessExitedError{}
return &proc.ProcessExitedError{Pid: dbp.Pid()}
}
g, err := proc.FindGoroutine(dbp, gid)
if err != nil {
......@@ -361,7 +361,7 @@ func (dbp *Process) SwitchGoroutine(gid int) error {
// Halt stops all threads.
func (dbp *Process) Halt() (err error) {
if dbp.exited {
return &proc.ProcessExitedError{}
return &proc.ProcessExitedError{Pid: dbp.Pid()}
}
for _, th := range dbp.threads {
if err := th.Halt(); err != nil {
......
......@@ -71,7 +71,7 @@ func FindFunctionLocation(p Process, funcName string, firstLine bool, lineOffset
// Next continues execution until the next source line.
func Next(dbp Process) (err error) {
if dbp.Exited() {
return &ProcessExitedError{}
return &ProcessExitedError{Pid: dbp.Pid()}
}
for _, bp := range dbp.Breakpoints() {
if bp.Internal() {
......@@ -91,6 +91,9 @@ func Next(dbp Process) (err error) {
// process. It will continue until it hits a breakpoint
// or is otherwise stopped.
func Continue(dbp Process) error {
if dbp.Exited() {
return &ProcessExitedError{Pid: dbp.Pid()}
}
dbp.ManualStopRequested()
for {
if dbp.ManualStopRequested() {
......@@ -213,7 +216,7 @@ func pickCurrentThread(dbp Process, trapthread Thread, threads []Thread) error {
// Will step into functions.
func Step(dbp Process) (err error) {
if dbp.Exited() {
return &ProcessExitedError{}
return &ProcessExitedError{Pid: dbp.Pid()}
}
for _, bp := range dbp.Breakpoints() {
if bp.Internal() {
......@@ -277,6 +280,9 @@ func andFrameoffCondition(cond ast.Expr, frameoff int64) ast.Expr {
// StepOut will continue until the current goroutine exits the
// function currently being executed or a deferred function is executed
func StepOut(dbp Process) error {
if dbp.Exited() {
return &ProcessExitedError{Pid: dbp.Pid()}
}
selg := dbp.SelectedGoroutine()
curthread := dbp.CurrentThread()
......@@ -349,7 +355,7 @@ type AllGCache interface {
// Delve cares about from the internal runtime G structure.
func GoroutinesInfo(dbp Process) ([]*G, error) {
if dbp.Exited() {
return nil, &ProcessExitedError{}
return nil, &ProcessExitedError{Pid: dbp.Pid()}
}
if dbp, ok := dbp.(AllGCache); ok {
if allGCache := dbp.AllGCache(); *allGCache != nil {
......@@ -453,6 +459,9 @@ func FindGoroutine(dbp Process, gid int) (*G, error) {
// ConvertEvalScope returns a new EvalScope in the context of the
// specified goroutine ID and stack frame.
func ConvertEvalScope(dbp Process, gid, frame int) (*EvalScope, error) {
if dbp.Exited() {
return nil, &ProcessExitedError{Pid: dbp.Pid()}
}
ct := dbp.CurrentThread()
g, err := FindGoroutine(dbp, gid)
if err != nil {
......
......@@ -42,7 +42,7 @@ type Stackframe struct {
Err error
}
// Stacktrace returns the stack trace for thread.
// ThreadStacktrace returns the stack trace for thread.
// Note the locations in the array are return addresses not call addresses.
func ThreadStacktrace(thread Thread, depth int) ([]Stackframe, error) {
regs, err := thread.Registers(false)
......
......@@ -457,8 +457,9 @@ func (d *Debugger) Threads() ([]*api.Thread, error) {
defer d.processMutex.Unlock()
if d.target.Exited() {
return nil, &proc.ProcessExitedError{}
return nil, proc.ProcessExitedError{Pid: d.ProcessPid()}
}
threads := []*api.Thread{}
for _, th := range d.target.ThreadList() {
threads = append(threads, api.ConvertThread(th))
......@@ -472,7 +473,7 @@ func (d *Debugger) FindThread(id int) (*api.Thread, error) {
defer d.processMutex.Unlock()
if d.target.Exited() {
return nil, &proc.ProcessExitedError{}
return nil, proc.ProcessExitedError{Pid: d.ProcessPid()}
}
for _, th := range d.target.ThreadList() {
......@@ -838,6 +839,10 @@ func (d *Debugger) Stacktrace(goroutineID, depth int, cfg *proc.LoadConfig) ([]a
d.processMutex.Lock()
defer d.processMutex.Unlock()
if d.target.Exited() {
return nil, proc.ProcessExitedError{Pid: d.ProcessPid()}
}
var rawlocs []proc.Stackframe
g, err := proc.FindGoroutine(d.target, goroutineID)
......@@ -893,6 +898,10 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat
d.processMutex.Lock()
defer d.processMutex.Unlock()
if d.target.Exited() {
return nil, &proc.ProcessExitedError{Pid: d.target.Pid()}
}
loc, err := parseLocationSpec(locStr)
if err != nil {
return nil, err
......@@ -910,12 +919,16 @@ func (d *Debugger) FindLocation(scope api.EvalScope, locStr string) ([]api.Locat
return locs, err
}
// Disassembles code between startPC and endPC
// Disassemble code between startPC and endPC
// if endPC == 0 it will find the function containing startPC and disassemble the whole function
func (d *Debugger) Disassemble(scope api.EvalScope, startPC, endPC uint64, flavour api.AssemblyFlavour) (api.AsmInstructions, error) {
d.processMutex.Lock()
defer d.processMutex.Unlock()
if d.target.Exited() {
return nil, &proc.ProcessExitedError{Pid: d.target.Pid()}
}
if endPC == 0 {
_, _, fn := d.target.BinInfo().PCToLine(startPC)
if fn == nil {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册