Merge "Call Delve using exec() instead of "dlv attach"."

This commit is contained in:
Lukács T. Berki
2020-05-27 08:33:32 +00:00
committed by Gerrit Code Review
2 changed files with 38 additions and 45 deletions

View File

@@ -15,9 +15,11 @@
package android package android
import ( import (
"fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"syscall"
"android/soong/env" "android/soong/env"
) )
@@ -30,28 +32,59 @@ import (
// a manifest regeneration. // a manifest regeneration.
var originalEnv map[string]string var originalEnv map[string]string
var SoongDelveListen string var soongDelveListen string
var SoongDelvePath string var soongDelvePath string
var soongDelveEnv []string
func init() { func init() {
// Delve support needs to read this environment variable very early, before NewConfig has created a way to // Delve support needs to read this environment variable very early, before NewConfig has created a way to
// access originalEnv with dependencies. Store the value where soong_build can find it, it will manually // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually
// ensure the dependencies are created. // ensure the dependencies are created.
SoongDelveListen = os.Getenv("SOONG_DELVE") soongDelveListen = os.Getenv("SOONG_DELVE")
SoongDelvePath, _ = exec.LookPath("dlv") soongDelvePath, _ = exec.LookPath("dlv")
originalEnv = make(map[string]string) originalEnv = make(map[string]string)
soongDelveEnv = []string{}
for _, env := range os.Environ() { for _, env := range os.Environ() {
idx := strings.IndexRune(env, '=') idx := strings.IndexRune(env, '=')
if idx != -1 { if idx != -1 {
originalEnv[env[:idx]] = env[idx+1:] originalEnv[env[:idx]] = env[idx+1:]
if env[:idx] != "SOONG_DELVE" {
soongDelveEnv = append(soongDelveEnv, env)
}
} }
} }
// Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
// variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc. // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
os.Clearenv() os.Clearenv()
} }
func ReexecWithDelveMaybe() {
if soongDelveListen == "" {
return
}
if soongDelvePath == "" {
fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
os.Exit(1)
}
dlvArgv := []string{
soongDelvePath,
"--listen=:" + soongDelveListen,
"--headless=true",
"--api-version=2",
"exec",
os.Args[0],
"--",
}
dlvArgv = append(dlvArgv, os.Args[1:]...)
os.Chdir(absSrcDir)
syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv)
fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
os.Exit(1)
}
// getenv checks either os.Getenv or originalEnv so that it works before or after the init() // getenv checks either os.Getenv or originalEnv so that it works before or after the init()
// function above. It doesn't add any dependencies on the environment variable, so it should // function above. It doesn't add any dependencies on the environment variable, so it should
// only be used for values that won't change. For values that might change use ctx.Config().Getenv. // only be used for values that won't change. For values that might change use ctx.Config().Getenv.

View File

@@ -18,12 +18,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv"
"strings"
"syscall"
"time"
"github.com/google/blueprint/bootstrap" "github.com/google/blueprint/bootstrap"
@@ -55,42 +50,7 @@ func newNameResolver(config android.Config) *android.NameResolver {
} }
func main() { func main() {
if android.SoongDelveListen != "" { android.ReexecWithDelveMaybe()
if android.SoongDelvePath == "" {
fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
os.Exit(1)
}
pid := strconv.Itoa(os.Getpid())
cmd := []string{android.SoongDelvePath,
"attach", pid,
"--headless",
"-l", android.SoongDelveListen,
"--api-version=2",
"--accept-multiclient",
"--log",
}
fmt.Println("Starting", strings.Join(cmd, " "))
dlv := exec.Command(cmd[0], cmd[1:]...)
dlv.Stdout = os.Stdout
dlv.Stderr = os.Stderr
dlv.Stdin = nil
// Put dlv into its own process group so we can kill it and the child process it starts.
dlv.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
err := dlv.Start()
if err != nil {
// Print the error starting dlv and continue.
fmt.Println(err)
} else {
// Kill the process group for dlv when soong_build exits.
defer syscall.Kill(-dlv.Process.Pid, syscall.SIGKILL)
// Wait to give dlv a chance to connect and pause the process.
time.Sleep(time.Second)
}
}
flag.Parse() flag.Parse()
// The top-level Blueprints file is passed as the first argument. // The top-level Blueprints file is passed as the first argument.