service: Make Halt work during tracing (#469)
While tracing delve may spend most of its time outside of proc.(*Process).Continue, which renders service/rpc/client.(*Client).Halt ineffective. This commit changes the implementation of service/rpc/client.(*Client).Halt to make it capable of stopping traces.
This commit is contained in:
parent
38127e5a00
commit
7820921b7e
@ -7,6 +7,7 @@ import (
|
|||||||
"net/rpc/jsonrpc"
|
"net/rpc/jsonrpc"
|
||||||
|
|
||||||
"github.com/derekparker/delve/service/api"
|
"github.com/derekparker/delve/service/api"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is a RPC service.Client.
|
// Client is a RPC service.Client.
|
||||||
@ -14,6 +15,8 @@ type RPCClient struct {
|
|||||||
addr string
|
addr string
|
||||||
processPid int
|
processPid int
|
||||||
client *rpc.Client
|
client *rpc.Client
|
||||||
|
haltMu sync.Mutex
|
||||||
|
haltReq bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a new RPCClient.
|
// NewClient creates a new RPCClient.
|
||||||
@ -50,8 +53,18 @@ func (c *RPCClient) GetState() (*api.DebuggerState, error) {
|
|||||||
|
|
||||||
func (c *RPCClient) Continue() <-chan *api.DebuggerState {
|
func (c *RPCClient) Continue() <-chan *api.DebuggerState {
|
||||||
ch := make(chan *api.DebuggerState)
|
ch := make(chan *api.DebuggerState)
|
||||||
|
c.haltMu.Lock()
|
||||||
|
c.haltReq = false
|
||||||
|
c.haltMu.Unlock()
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
c.haltMu.Lock()
|
||||||
|
if c.haltReq {
|
||||||
|
c.haltMu.Unlock()
|
||||||
|
close(ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.haltMu.Unlock()
|
||||||
state := new(api.DebuggerState)
|
state := new(api.DebuggerState)
|
||||||
err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, state)
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Continue}, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -125,6 +138,9 @@ func (c *RPCClient) SwitchGoroutine(goroutineID int) (*api.DebuggerState, error)
|
|||||||
|
|
||||||
func (c *RPCClient) Halt() (*api.DebuggerState, error) {
|
func (c *RPCClient) Halt() (*api.DebuggerState, error) {
|
||||||
state := new(api.DebuggerState)
|
state := new(api.DebuggerState)
|
||||||
|
c.haltMu.Lock()
|
||||||
|
c.haltReq = true
|
||||||
|
c.haltMu.Unlock()
|
||||||
err := c.call("Command", &api.DebuggerCommand{Name: api.Halt}, state)
|
err := c.call("Command", &api.DebuggerCommand{Name: api.Halt}, state)
|
||||||
return state, err
|
return state, err
|
||||||
}
|
}
|
||||||
|
@ -438,12 +438,14 @@ func restart(t *Term, ctx callContext, args string) error {
|
|||||||
|
|
||||||
func cont(t *Term, ctx callContext, args string) error {
|
func cont(t *Term, ctx callContext, args string) error {
|
||||||
stateChan := t.client.Continue()
|
stateChan := t.client.Continue()
|
||||||
for state := range stateChan {
|
var state *api.DebuggerState
|
||||||
|
for state = range stateChan {
|
||||||
if state.Err != nil {
|
if state.Err != nil {
|
||||||
return state.Err
|
return state.Err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
}
|
}
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,6 +455,7 @@ func step(t *Term, ctx callContext, args string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,6 +465,7 @@ func stepInstruction(t *Term, ctx callContext, args string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,6 +475,7 @@ func next(t *Term, ctx callContext, args string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,6 +841,7 @@ func listCommand(t *Term, ctx callContext, args string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,9 +979,6 @@ func printcontext(t *Term, state *api.DebuggerState) error {
|
|||||||
|
|
||||||
printcontextThread(t, state.CurrentThread)
|
printcontextThread(t, state.CurrentThread)
|
||||||
|
|
||||||
if state.CurrentThread.Breakpoint == nil || !state.CurrentThread.Breakpoint.Tracepoint || state.CurrentThread.BreakpointInfo == nil {
|
|
||||||
return printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user