Merge "Call Delve using exec() instead of "dlv attach"."
This commit is contained in:
@@ -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.
|
||||||
|
@@ -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.
|
||||||
|
Reference in New Issue
Block a user