mirror of
https://github.com/go-delve/delve.git
synced 2025-10-27 12:05:21 +08:00
cmd/dlv: add flag to make headless server accept multiple clients
This commit is contained in:
@ -32,6 +32,8 @@ var (
|
||||
Log bool
|
||||
// Headless is whether to run without terminal.
|
||||
Headless bool
|
||||
// Allows multiple clients to connect to the same server
|
||||
AcceptMulti bool
|
||||
// Addr is the debugging server listen address.
|
||||
Addr string
|
||||
// InitFile is the path to initialization file.
|
||||
@ -74,6 +76,7 @@ func init() {
|
||||
rootCommand.PersistentFlags().StringVarP(&Addr, "listen", "l", "localhost:0", "Debugging server listen address.")
|
||||
rootCommand.PersistentFlags().BoolVarP(&Log, "log", "", false, "Enable debugging server logging.")
|
||||
rootCommand.PersistentFlags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
|
||||
rootCommand.PersistentFlags().BoolVarP(&AcceptMulti, "accept-multiclient", "", false, "Allows a headless server to accept multiple client connection. Note that the server API is not reentrant and clients will have to coordinate")
|
||||
rootCommand.PersistentFlags().StringVar(&InitFile, "init", "", "Init file, executed by the terminal client.")
|
||||
rootCommand.PersistentFlags().StringVar(&BuildFlags, "build-flags", buildFlagsDefault, "Build flags, to be passed to the compiler.")
|
||||
|
||||
@ -351,6 +354,7 @@ func execute(attachPid int, processArgs []string, conf *config.Config) int {
|
||||
Listener: listener,
|
||||
ProcessArgs: processArgs,
|
||||
AttachPid: attachPid,
|
||||
AcceptMulti: AcceptMulti,
|
||||
}, Log)
|
||||
if err := server.Run(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
||||
@ -16,4 +16,7 @@ type Config struct {
|
||||
// AttachPid is the PID of an existing process to which the debugger should
|
||||
// attach.
|
||||
AttachPid int
|
||||
// AcceptMulti configures the server to accept multiple connection
|
||||
// Note that the server API is not reentrant and clients will have to coordinate
|
||||
AcceptMulti bool
|
||||
}
|
||||
|
||||
@ -23,6 +23,8 @@ type RPCServer struct {
|
||||
config *service.Config
|
||||
// listener is used to serve HTTP.
|
||||
listener net.Listener
|
||||
// stopChan is used to stop the listener goroutine
|
||||
stopChan chan struct{}
|
||||
// debugger is a debugger service.
|
||||
debugger *debugger.Debugger
|
||||
}
|
||||
@ -38,13 +40,22 @@ func NewServer(config *service.Config, logEnabled bool) *ServerImpl {
|
||||
&RPCServer{
|
||||
config: config,
|
||||
listener: config.Listener,
|
||||
stopChan: make(chan struct{}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Stop detaches from the debugger and waits for it to stop.
|
||||
func (s *ServerImpl) Stop(kill bool) error {
|
||||
return s.s.debugger.Detach(kill)
|
||||
if s.s.config.AcceptMulti {
|
||||
close(s.s.stopChan)
|
||||
s.s.listener.Close()
|
||||
}
|
||||
err := s.s.debugger.Detach(kill)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run starts a debugger and exposes it with an HTTP server. The debugger
|
||||
@ -60,16 +71,27 @@ func (s *ServerImpl) Run() error {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
c, err := s.s.listener.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer s.s.listener.Close()
|
||||
rpcs := grpc.NewServer()
|
||||
rpcs.Register(s.s)
|
||||
|
||||
rpcs := grpc.NewServer()
|
||||
rpcs.Register(s.s)
|
||||
rpcs.ServeCodec(jsonrpc.NewServerCodec(c))
|
||||
go func() {
|
||||
defer s.s.listener.Close()
|
||||
for {
|
||||
c, err := s.s.listener.Accept()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-s.s.stopChan:
|
||||
// We were supposed to exit, do nothing and return
|
||||
return
|
||||
default:
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
go rpcs.ServeCodec(jsonrpc.NewServerCodec(c))
|
||||
if !s.s.config.AcceptMulti {
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user