diff --git a/proc/proc.go b/proc/proc.go index 3231111a..8c2478fb 100644 --- a/proc/proc.go +++ b/proc/proc.go @@ -772,3 +772,9 @@ func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) { return &out, nil } + +func (dbp *Process) postExit() { + dbp.exited = true + close(dbp.ptraceChan) + close(dbp.ptraceDoneChan) +} diff --git a/proc/proc_darwin.go b/proc/proc_darwin.go index 3ab96d19..a947814f 100644 --- a/proc/proc_darwin.go +++ b/proc/proc_darwin.go @@ -116,7 +116,7 @@ func (dbp *Process) Kill() (err error) { break } } - dbp.exited = true + dbp.postExit() return } @@ -276,7 +276,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { if err != nil { return nil, err } - dbp.exited = true + dbp.postExit() return nil, ProcessExitedError{Pid: dbp.Pid, Status: status.ExitStatus()} case C.MACH_RCV_INTERRUPTED: diff --git a/proc/proc_linux.go b/proc/proc_linux.go index 5df118e8..6acd3c33 100644 --- a/proc/proc_linux.go +++ b/proc/proc_linux.go @@ -78,7 +78,7 @@ func (dbp *Process) Kill() (err error) { if _, _, err = dbp.wait(dbp.Pid, 0); err != nil { return } - dbp.exited = true + dbp.postExit() return } @@ -254,7 +254,7 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) { } if status.Exited() { if wpid == dbp.Pid { - dbp.exited = true + dbp.postExit() return nil, ProcessExitedError{Pid: wpid, Status: status.ExitStatus()} } delete(dbp.Threads, wpid) diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index 4b9c9f1f..aa6eebe0 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -105,6 +105,10 @@ func (d *Debugger) Restart() error { } func (d *Debugger) State() (*api.DebuggerState, error) { + if d.process.Exited() { + return nil, proc.ProcessExitedError{Pid: d.ProcessPid()} + } + var ( state *api.DebuggerState thread *api.Thread @@ -226,12 +230,9 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er case api.Continue: log.Print("continuing") err = d.process.Continue() - state, stateErr := d.State() - if stateErr != nil { - return state, stateErr - } if err != nil { if exitedErr, exited := err.(proc.ProcessExitedError); exited { + state := &api.DebuggerState{} state.Exited = true state.ExitStatus = exitedErr.Status state.Err = errors.New(exitedErr.Error()) @@ -239,6 +240,10 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er } return nil, err } + state, stateErr := d.State() + if stateErr != nil { + return state, stateErr + } err = d.collectBreakpointInformation(state) return state, err diff --git a/service/test/integration_test.go b/service/test/integration_test.go index d3a3aa41..22d8caff 100644 --- a/service/test/integration_test.go +++ b/service/test/integration_test.go @@ -144,14 +144,8 @@ func TestClientServer_exit(t *testing.T) { t.Fatalf("Expected exit after continue: %v", state) } state, err = c.GetState() - if err != nil { - t.Fatal(err) - } - if state.CurrentThread == nil { - t.Fatalf("Expected CurrentThread") - } - if e, a := true, state.Exited; e != a { - t.Fatalf("Expected exited %v, got %v", e, a) + if err == nil { + t.Fatal("Expected error on querying state from exited process") } }) }