mirror of
https://github.com/go-delve/delve.git
synced 2025-10-27 20:23:41 +08:00
cmd/dlv: add --continue to continue process on launch/attach (#1585)
* Add --continue to continue process on launch/attach * Add small test of --continue * regenerate usage docs * minor cleanup * Use similar approach to `trace` and connect and detach using a client instance * back out previous attempt * regen usage doc * fix up continue test * fix TestContinue to properly test --continue * back out unnecessary changes * update faq
This commit is contained in:
committed by
Derek Parker
parent
f67239f302
commit
cb65877297
@ -28,14 +28,10 @@ And then connect to it from outside the container:
|
||||
dlv connect :4040
|
||||
```
|
||||
|
||||
The program will not start executing until you connect to Delve and send the `continue` command. If you want the program to start immediately you can do that by:
|
||||
|
||||
1. Passing the `--accept-multiclient` option to the headless instance of delve: `dlv exec --headless --listen :4040 --accept-multiclient /path/to/executable`
|
||||
2. Using the following script:
|
||||
The program will not start executing until you connect to Delve and send the `continue` command. If you want the program to start immediately you can do that by passing the `--continue` and `--accept-multiclient` options to Delve:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
while true; do sleep 1; dlv connect :4040 --init <(echo quit -c) && exit; done
|
||||
dlv exec --headless --continue --listen :4040 --accept-multiclient /path/to/executable
|
||||
```
|
||||
|
||||
Note that the connection to Delve is unauthenticated and will allow arbitrary remote code execution: *do not do this in production*.
|
||||
|
||||
@ -19,6 +19,7 @@ dlv debug [package]
|
||||
### Options
|
||||
|
||||
```
|
||||
--continue Continue the debugged process on start.
|
||||
--output string Output path for the binary. (default "./__debug_bin")
|
||||
```
|
||||
|
||||
|
||||
@ -17,6 +17,12 @@ or later, -gcflags="-N -l" on earlier versions of Go.
|
||||
dlv exec <path/to/binary>
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--continue Continue the debugged process on start.
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
|
||||
@ -33,6 +33,8 @@ var (
|
||||
LogDest string
|
||||
// Headless is whether to run without terminal.
|
||||
Headless bool
|
||||
// ContinueOnStart is whether to continue the process on startup
|
||||
ContinueOnStart bool
|
||||
// APIVersion is the requested API version while running headless
|
||||
APIVersion int
|
||||
// AcceptMulti allows multiple clients to connect to the same server
|
||||
@ -172,6 +174,7 @@ session.`,
|
||||
Run: debugCmd,
|
||||
}
|
||||
debugCommand.Flags().String("output", "./__debug_bin", "Output path for the binary.")
|
||||
debugCommand.Flags().BoolVar(&ContinueOnStart, "continue", false, "Continue the debugged process on start.")
|
||||
RootCommand.AddCommand(debugCommand)
|
||||
|
||||
// 'exec' subcommand.
|
||||
@ -195,6 +198,7 @@ or later, -gcflags="-N -l" on earlier versions of Go.`,
|
||||
os.Exit(execute(0, args, conf, "", executingExistingFile))
|
||||
},
|
||||
}
|
||||
execCommand.Flags().BoolVar(&ContinueOnStart, "continue", false, "Continue the debugged process on start.")
|
||||
RootCommand.AddCommand(execCommand)
|
||||
|
||||
// Deprecated 'run' subcommand.
|
||||
@ -561,7 +565,17 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile
|
||||
defer logflags.Close()
|
||||
|
||||
if Headless && (InitFile != "") {
|
||||
fmt.Fprint(os.Stderr, "Warning: init file ignored\n")
|
||||
fmt.Fprint(os.Stderr, "Warning: init file ignored with --headless\n")
|
||||
}
|
||||
if ContinueOnStart {
|
||||
if !Headless {
|
||||
fmt.Fprint(os.Stderr, "Error: --continue only works with --headless; use an init file\n")
|
||||
return 1
|
||||
}
|
||||
if !AcceptMulti {
|
||||
fmt.Fprint(os.Stderr, "Error: --continue requires --accept-multiclient\n")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
if !Headless && AcceptMulti {
|
||||
@ -633,6 +647,11 @@ func execute(attachPid int, processArgs []string, conf *config.Config, coreFile
|
||||
|
||||
var status int
|
||||
if Headless {
|
||||
if ContinueOnStart {
|
||||
var client *rpc2.RPCClient
|
||||
client = rpc2.NewClient(listener.Addr().String())
|
||||
client.Disconnect(true) // true = continue after disconnect
|
||||
}
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT)
|
||||
select {
|
||||
|
||||
@ -218,6 +218,39 @@ func TestOutput(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestContinue verifies that the debugged executable starts immediately with --continue
|
||||
func TestContinue(t *testing.T) {
|
||||
const listenAddr = "localhost:40573"
|
||||
|
||||
dlvbin, tmpdir := getDlvBin(t)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
buildtestdir := filepath.Join(protest.FindFixturesDir(), "buildtest")
|
||||
cmd := exec.Command(dlvbin, "debug", "--headless", "--continue", "--accept-multiclient", "--listen", listenAddr)
|
||||
cmd.Dir = buildtestdir
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
assertNoError(err, t, "stderr pipe")
|
||||
if err := cmd.Start(); err != nil {
|
||||
t.Fatalf("could not start headless instance: %v", err)
|
||||
}
|
||||
|
||||
scan := bufio.NewScanner(stdout)
|
||||
// wait for the debugger to start
|
||||
for scan.Scan() {
|
||||
t.Log(scan.Text())
|
||||
if scan.Text() == "hello world!" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// and detach from and kill the headless instance
|
||||
client := rpc2.NewClient(listenAddr)
|
||||
if err := client.Detach(true); err != nil {
|
||||
t.Fatalf("error detaching from headless instance: %v", err)
|
||||
}
|
||||
cmd.Wait()
|
||||
}
|
||||
|
||||
func checkAutogenDoc(t *testing.T, filename, gencommand string, generated []byte) {
|
||||
saved := slurpFile(t, filepath.Join(projectRoot(), filename))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user