func withTestTerminal(name string, t testing.TB, fn func(*FakeTerminal)) { os.Setenv("TERM", "dumb") listener, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("couldn't start listener: %s\n", err) } defer listener.Close() server := rpc2.NewServer(&service.Config{ Listener: listener, ProcessArgs: []string{test.BuildFixture(name).Path}, }, false) if err := server.Run(); err != nil { t.Fatal(err) } client := rpc2.NewClient(listener.Addr().String()) defer func() { client.Detach(true) }() ft := &FakeTerminal{ t: t, Term: New(client, nil), } fn(ft) }
func TestRestart_attachPid(t *testing.T) { // Assert it does not work and returns error. // We cannot restart a process we did not spawn. server := rpc2.NewServer(&service.Config{ Listener: nil, AttachPid: 999, }, false) if err := server.Restart(); err == nil { t.Fatal("expected error on restart after attaching to pid but got none") } }
// Run starts a debugger and exposes it with an HTTP server. The debugger // itself can be stopped with the `detach` API. Run blocks until the HTTP // server stops. func (s *ServerImpl) Run() error { var err error if s.config.APIVersion < 2 { s.config.APIVersion = 1 } if s.config.APIVersion > 2 { return fmt.Errorf("unknown API version") } // Create and start the debugger if s.debugger, err = debugger.New(&debugger.Config{ ProcessArgs: s.config.ProcessArgs, AttachPid: s.config.AttachPid, }); err != nil { return err } s.s1 = rpc1.NewServer(s.config, s.debugger) s.s2 = rpc2.NewServer(s.config, s.debugger) rpcServer := &RPCServer{s} s.methodMaps = make([]map[string]*methodType, 2) s.methodMaps[0] = map[string]*methodType{} s.methodMaps[1] = map[string]*methodType{} suitableMethods(s.s1, s.methodMaps[0]) suitableMethods(rpcServer, s.methodMaps[0]) suitableMethods(s.s2, s.methodMaps[1]) suitableMethods(rpcServer, s.methodMaps[1]) go func() { defer s.listener.Close() for { c, err := s.listener.Accept() if err != nil { select { case <-s.stopChan: // We were supposed to exit, do nothing and return return default: panic(err) } } go s.serveJSONCodec(c) if !s.config.AcceptMulti { break } } }() return nil }
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 := rpc2.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 withTestClient2(name string, t *testing.T, fn func(c service.Client)) { listener, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("couldn't start listener: %s\n", err) } defer listener.Close() server := rpc2.NewServer(&service.Config{ Listener: listener, ProcessArgs: []string{protest.BuildFixture(name).Path}, }, false) if err := server.Run(); err != nil { t.Fatal(err) } client := rpc2.NewClient(listener.Addr().String()) defer func() { client.Detach(true) }() fn(client) }
func execute(attachPid int, processArgs []string, conf *config.Config, kind executeKind) int { // Make a TCP listener listener, err := net.Listen("tcp", Addr) if err != nil { fmt.Printf("couldn't start listener: %s\n", err) return 1 } defer listener.Close() if Headless && (InitFile != "") { fmt.Fprintf(os.Stderr, "Warning: init file ignored\n") } var server interface { Run() error Stop(bool) error } if !Headless { ApiVersion = 2 } // Create and start a debugger server switch ApiVersion { case 1: server = rpc1.NewServer(&service.Config{ Listener: listener, ProcessArgs: processArgs, AttachPid: attachPid, AcceptMulti: AcceptMulti, }, Log) case 2: server = rpc2.NewServer(&service.Config{ Listener: listener, ProcessArgs: processArgs, AttachPid: attachPid, AcceptMulti: AcceptMulti, }, Log) default: fmt.Println("Unknown API version %d", ApiVersion) return 1 } if err := server.Run(); err != nil { if err == api.NotExecutableErr { switch kind { case executingGeneratedFile: fmt.Fprintln(os.Stderr, "Can not debug non-main package") return 1 case executingExistingFile: fmt.Fprintf(os.Stderr, "%s is not executable\n", processArgs[0]) return 1 default: // fallthrough } } fmt.Fprintln(os.Stderr, err) return 1 } var status int if Headless { // Print listener address fmt.Printf("API server listening at: %s\n", listener.Addr()) ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT) <-ch err = server.Stop(true) } else { // Create and start a terminal var client service.Client client = rpc2.NewClient(listener.Addr().String()) term := terminal.New(client, conf) term.InitFile = InitFile status, err = term.Run() } if err != nil { fmt.Println(err) } return status }
func traceCmd(cmd *cobra.Command, args []string) { status := func() int { var regexp string var processArgs []string dlvArgs, targetArgs := splitArgs(cmd, args) if traceAttachPid == 0 { var pkg string switch len(dlvArgs) { case 1: regexp = args[0] case 2: pkg = args[0] regexp = args[1] } if err := gobuild(debugname, pkg); err != nil { return 1 } defer os.Remove("./" + debugname) processArgs = append([]string{"./" + debugname}, targetArgs...) } // Make a TCP listener listener, err := net.Listen("tcp", Addr) if err != nil { fmt.Printf("couldn't start listener: %s\n", err) return 1 } defer listener.Close() // Create and start a debug server server := rpc2.NewServer(&service.Config{ Listener: listener, ProcessArgs: processArgs, AttachPid: traceAttachPid, }, Log) if err := server.Run(); err != nil { fmt.Fprintln(os.Stderr, err) return 1 } client := rpc2.NewClient(listener.Addr().String()) funcs, err := client.ListFunctions(regexp) if err != nil { fmt.Fprintln(os.Stderr, err) return 1 } for i := range funcs { _, err = client.CreateBreakpoint(&api.Breakpoint{FunctionName: funcs[i], Tracepoint: true, Line: -1, Stacktrace: traceStackDepth, LoadArgs: &terminal.ShortLoadConfig}) if err != nil { fmt.Fprintln(os.Stderr, err) return 1 } } cmds := terminal.DebugCommands(client) t := terminal.New(client, nil) defer t.Close() err = cmds.Call("continue", "", t) if err != nil { fmt.Fprintln(os.Stderr, err) return 1 } return 0 }() os.Exit(status) }