From 50f6382307d8574cba170a2b0b12e4dc948f6d05 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 26 Jun 2017 20:45:13 +0200 Subject: [PATCH] dlv: make headless servers quit automatically when client disconnects (#895) --- cmd/dlv/cmds/commands.go | 9 ++++++++- cmd/dlv/dlv_test.go | 15 +++------------ pkg/proc/gdbserial/gdbserver.go | 1 + service/config.go | 3 +++ service/rpc2/client.go | 1 + service/rpccommon/server.go | 3 +++ 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/cmd/dlv/cmds/commands.go b/cmd/dlv/cmds/commands.go index 79a94b11..83ad7bcf 100644 --- a/cmd/dlv/cmds/commands.go +++ b/cmd/dlv/cmds/commands.go @@ -455,6 +455,8 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile Stop(bool) error } + disconnectChan := make(chan struct{}) + // Create and start a debugger server switch APIVersion { case 1, 2: @@ -467,6 +469,8 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile WorkingDir: WorkingDir, Backend: Backend, CoreFile: coreFile, + + DisconnectChan: disconnectChan, }, Log) default: fmt.Printf("Unknown API version: %d\n", APIVersion) @@ -496,7 +500,10 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile fmt.Printf("API server listening at: %s\n", listener.Addr()) ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT) - <-ch + select { + case <-ch: + case <-disconnectChan: + } err = server.Stop(true) } else { // Create and start a terminal diff --git a/cmd/dlv/dlv_test.go b/cmd/dlv/dlv_test.go index 7ebfe4e7..471daba9 100644 --- a/cmd/dlv/dlv_test.go +++ b/cmd/dlv/dlv_test.go @@ -76,17 +76,6 @@ func TestBuild(t *testing.T) { stdout, err := cmd.StdoutPipe() assertNoError(err, t, "stdout pipe") cmd.Start() - done := make(chan struct{}) - defer func() { - if runtime.GOOS != "windows" { - cmd.Process.Signal(os.Interrupt) - } else { - // sending os.Interrupt on windows is not supported - cmd.Process.Kill() - } - <-done - cmd.Wait() - }() scan := bufio.NewScanner(stdout) // wait for the debugger to start @@ -95,7 +84,6 @@ func TestBuild(t *testing.T) { for scan.Scan() { // keep pipe empty } - close(done) }() client := rpc2.NewClient(listenAddr) @@ -104,4 +92,7 @@ func TestBuild(t *testing.T) { if !state.Exited { t.Fatal("Program did not exit") } + + client.Detach(true) + cmd.Wait() } diff --git a/pkg/proc/gdbserial/gdbserver.go b/pkg/proc/gdbserial/gdbserver.go index bf9670dd..4df8f19d 100644 --- a/pkg/proc/gdbserial/gdbserver.go +++ b/pkg/proc/gdbserial/gdbserver.go @@ -698,6 +698,7 @@ func (p *Process) Detach(kill bool) error { if p.process != nil { p.process.Kill() <-p.waitChan + p.process = nil } return p.bi.Close() } diff --git a/service/config.go b/service/config.go index 42741b80..ecd40826 100644 --- a/service/config.go +++ b/service/config.go @@ -31,4 +31,7 @@ type Config struct { // Selects server backend. Backend string + + // DisconnectChan will be closed by the server when the client disconnects + DisconnectChan chan<- struct{} } diff --git a/service/rpc2/client.go b/service/rpc2/client.go index 0a8c0320..eb31cfd6 100644 --- a/service/rpc2/client.go +++ b/service/rpc2/client.go @@ -45,6 +45,7 @@ func (c *RPCClient) LastModified() time.Time { } func (c *RPCClient) Detach(kill bool) error { + defer c.client.Close() out := new(DetachOut) return c.call("Detach", DetachIn{kill}, out) } diff --git a/service/rpccommon/server.go b/service/rpccommon/server.go index 7c9e9235..b89948e0 100644 --- a/service/rpccommon/server.go +++ b/service/rpccommon/server.go @@ -321,6 +321,9 @@ func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) { } } codec.Close() + if !s.config.AcceptMulti && s.config.DisconnectChan != nil { + close(s.config.DisconnectChan) + } } // A value sent as a placeholder for the server's response value when the server