From 29ed16984851be78fadf8e70ad908d37cd3c47f3 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Fri, 26 Jun 2015 23:05:15 -0500 Subject: [PATCH] Return error when invoking Delve with invalid path Fixes #154 --- cmd/dlv/main.go | 13 ++++++++++++- proc/proc_darwin.go | 11 +++++++++++ service/debugger/debugger.go | 4 ++-- service/rpc/server.go | 19 +++++++++++-------- service/test/integration_test.go | 19 ++++++++++++++++++- 5 files changed, 54 insertions(+), 12 deletions(-) diff --git a/cmd/dlv/main.go b/cmd/dlv/main.go index 11f57ce5..4a2e124e 100644 --- a/cmd/dlv/main.go +++ b/cmd/dlv/main.go @@ -61,6 +61,13 @@ func main() { os.Exit(0) } + defer func() { + if err := recover(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + }() + status := run(addr, logEnabled, headless) fmt.Println("[Hope I was of service hunting your bug!]") os.Exit(status) @@ -121,6 +128,7 @@ func run(addr string, logEnabled, headless bool) int { fmt.Printf("couldn't start listener: %s\n", err) return 1 } + defer listener.Close() // Create and start a debugger server var server service.Server @@ -129,7 +137,10 @@ func run(addr string, logEnabled, headless bool) int { ProcessArgs: processArgs, AttachPid: attachPid, }, logEnabled) - go server.Run() + if err := server.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) + return 1 + } var status int if !headless { diff --git a/proc/proc_darwin.go b/proc/proc_darwin.go index 0fd35149..dfb0be8d 100644 --- a/proc/proc_darwin.go +++ b/proc/proc_darwin.go @@ -9,6 +9,7 @@ import ( "debug/macho" "fmt" "os" + "os/exec" "path/filepath" "sync" "unsafe" @@ -38,8 +39,18 @@ func Launch(cmd []string) (*Process, error) { if err != nil { return nil, err } + if filepath.Base(cmd[0]) == cmd[0] { + if _, err := exec.LookPath(cmd[0]); err != nil { + return nil, err + } + } argv0 := C.CString(argv0Go) + // Make sure the binary exists. + if _, err := os.Stat(argv0Go); err != nil { + return nil, err + } + argvSlice := make([]*C.char, 0, len(cmd)) for _, arg := range cmd { argvSlice = append(argvSlice, C.CString(arg)) diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index e9fc23c2..1460ef5a 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -46,14 +46,14 @@ func New(config *Config) (*Debugger, error) { log.Printf("attaching to pid %d", d.config.AttachPid) p, err := proc.Attach(d.config.AttachPid) if err != nil { - return nil, fmt.Errorf("couldn't attach to pid %d: %s", d.config.AttachPid, err) + return nil, fmt.Errorf("could not attach to pid %d: %s", d.config.AttachPid, err) } d.process = p } else { log.Printf("launching process with args: %v", d.config.ProcessArgs) p, err := proc.Launch(d.config.ProcessArgs) if err != nil { - return nil, fmt.Errorf("couldn't launch process: %s", err) + return nil, fmt.Errorf("could not launch process: %s", err) } d.process = p } diff --git a/service/rpc/server.go b/service/rpc/server.go index 6bc23d6b..f306a604 100644 --- a/service/rpc/server.go +++ b/service/rpc/server.go @@ -45,11 +45,7 @@ func (s *RPCServer) Stop(kill bool) error { // itself can be stopped with the `detach` API. Run blocks until the HTTP // server stops. func (s *RPCServer) Run() error { - c, err := s.listener.Accept() - if err != nil { - return err - } - + var err error // Create and start the debugger if s.debugger, err = debugger.New(&debugger.Config{ ProcessArgs: s.config.ProcessArgs, @@ -58,9 +54,16 @@ func (s *RPCServer) Run() error { return err } - rpcs := grpc.NewServer() - rpcs.Register(s) - rpcs.ServeCodec(jsonrpc.NewServerCodec(c)) + go func() { + c, err := s.listener.Accept() + if err != nil { + panic(err) + } + + rpcs := grpc.NewServer() + rpcs.Register(s) + rpcs.ServeCodec(jsonrpc.NewServerCodec(c)) + }() return nil } diff --git a/service/test/integration_test.go b/service/test/integration_test.go index 27f478b5..58fa6063 100644 --- a/service/test/integration_test.go +++ b/service/test/integration_test.go @@ -33,7 +33,9 @@ func withTestClient(name string, t *testing.T, fn func(c service.Client)) { Listener: listener, ProcessArgs: []string{protest.BuildFixture(name).Path}, }, false) - go server.Run() + if err := server.Run(); err != nil { + t.Fatal(err) + } client := rpc.NewClient(listener.Addr().String()) defer func() { client.Detach(true) @@ -42,6 +44,21 @@ func withTestClient(name string, t *testing.T, fn func(c service.Client)) { fn(client) } +func TestRunWithInvalidPath(t *testing.T) { + listener, err := net.Listen("tcp", "localhost:0") + if err != nil { + t.Fatalf("couldn't start listener: %s\n", err) + } + defer listener.Close() + server := rpc.NewServer(&service.Config{ + Listener: listener, + ProcessArgs: []string{"invalid_path"}, + }, false) + if err := server.Run(); err == nil { + t.Fatal("Expected Run to return error for invalid program path") + } +} + func TestClientServer_exit(t *testing.T) { withTestClient("continuetestprog", t, func(c service.Client) { state, err := c.GetState()